Fix graph facilities handling in writer component class
[babeltrace.git] / common / common.c
index 47186e164a74e23b83270ed882d38209fc87a173..8d202ea5f743a50ad290018f87f0ea02e1f22e25 100644 (file)
  * SOFTWARE.
  */
 
+#include <unistd.h>
 #include <string.h>
 #include <sys/types.h>
 #include <pwd.h>
 #include <unistd.h>
 #include <assert.h>
+#include <ctype.h>
 #include <glib.h>
 #include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/common-internal.h>
 
 #define SYSTEM_PLUGIN_PATH     INSTALL_LIBDIR "/babeltrace/plugins"
 #define HOME_ENV_VAR           "HOME"
@@ -163,3 +166,503 @@ error:
 end:
        return ret;
 }
+
+BT_HIDDEN
+bool bt_common_colors_supported(void)
+{
+       static bool supports_colors = false;
+       static bool supports_colors_set = false;
+       const char *term;
+
+       if (supports_colors_set) {
+               goto end;
+       }
+
+       supports_colors_set = true;
+
+       term = getenv("TERM");
+       if (!term) {
+               goto end;
+       }
+
+       if (strncmp(term, "xterm", 5) != 0 &&
+                       strncmp(term, "rxvt", 4) != 0 &&
+                       strncmp(term, "konsole", 7) != 0 &&
+                       strncmp(term, "gnome", 5) != 0 &&
+                       strncmp(term, "screen", 5) != 0 &&
+                       strncmp(term, "tmux", 4) != 0 &&
+                       strncmp(term, "putty", 5) != 0) {
+               goto end;
+       }
+
+       if (!isatty(1)) {
+               goto end;
+       }
+
+       supports_colors = true;
+
+end:
+       return supports_colors;
+}
+
+BT_HIDDEN
+const char *bt_common_color_reset(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_RESET : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_bold(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_BOLD : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_default(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_FG_DEFAULT : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_red(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_FG_RED : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_green(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_FG_GREEN : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_yellow(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_FG_YELLOW : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_blue(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_FG_BLUE : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_magenta(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_FG_MAGENTA : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_cyan(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_FG_CYAN : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_fg_light_gray(void)
+{
+       return bt_common_colors_supported() ?
+               BT_COMMON_COLOR_FG_LIGHT_GRAY : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_bg_default(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_BG_DEFAULT : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_bg_red(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_BG_RED : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_bg_green(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_BG_GREEN : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_bg_yellow(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_BG_YELLOW : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_bg_blue(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_BG_BLUE : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_bg_magenta(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_BG_MAGENTA : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_bg_cyan(void)
+{
+       return bt_common_colors_supported() ? BT_COMMON_COLOR_BG_CYAN : "";
+}
+
+BT_HIDDEN
+const char *bt_common_color_bg_light_gray(void)
+{
+       return bt_common_colors_supported() ?
+               BT_COMMON_COLOR_BG_LIGHT_GRAY : "";
+}
+
+BT_HIDDEN
+GString *bt_common_string_until(const char *input, const char *escapable_chars,
+               const char *end_chars, size_t *end_pos)
+{
+       GString *output = g_string_new(NULL);
+       const char *ch;
+       const char *es_char;
+       const char *end_char;
+
+       if (!output) {
+               goto error;
+       }
+
+       for (ch = input; *ch != '\0'; ch++) {
+               if (*ch == '\\') {
+                       bool continue_loop = false;
+
+                       if (ch[1] == '\0') {
+                               /* `\` at the end of the string: append `\` */
+                               g_string_append_c(output, *ch);
+                               ch++;
+                               goto set_end_pos;
+                       }
+
+                       for (es_char = escapable_chars; *es_char != '\0'; es_char++) {
+                               if (ch[1] == *es_char) {
+                                       /*
+                                        * `\` followed by an escapable
+                                        * character: append the escaped
+                                        * character only.
+                                        */
+                                       g_string_append_c(output, ch[1]);
+                                       ch++;
+                                       continue_loop = true;
+                                       break;
+                               }
+                       }
+
+                       if (continue_loop) {
+                               continue;
+                       }
+
+                       /*
+                        * `\` followed by a non-escapable character:
+                        * append `\` and the character.
+                        */
+                       g_string_append_c(output, *ch);
+                       g_string_append_c(output, ch[1]);
+                       ch++;
+                       continue;
+               } else {
+                       for (end_char = end_chars; *end_char != '\0'; end_char++) {
+                               if (*ch == *end_char) {
+                                       /*
+                                        * End character found:
+                                        * terminate this loop.
+                                        */
+                                       goto set_end_pos;
+                               }
+                       }
+
+                       /* Normal character: append */
+                       g_string_append_c(output, *ch);
+               }
+       }
+
+set_end_pos:
+       if (end_pos) {
+               *end_pos = ch - input;
+       }
+
+       goto end;
+
+error:
+       if (output) {
+               g_string_free(output, TRUE);
+       }
+
+end:
+       return output;
+}
+
+BT_HIDDEN
+GString *bt_common_shell_quote(const char *input)
+{
+       GString *output = g_string_new(NULL);
+       const char *ch;
+       bool no_quote = true;
+
+       if (!output) {
+               goto end;
+       }
+
+       if (strlen(input) == 0) {
+               g_string_assign(output, "''");
+               goto end;
+       }
+
+       for (ch = input; *ch != '\0'; ch++) {
+               const char c = *ch;
+
+               if (!g_ascii_isalpha(c) && !g_ascii_isdigit(c) && c != '_' &&
+                               c != '@' && c != '%' && c != '+' && c != '=' &&
+                               c != ':' && c != ',' && c != '.' && c != '/' &&
+                               c != '-') {
+                       no_quote = false;
+                       break;
+               }
+       }
+
+       if (no_quote) {
+               g_string_assign(output, input);
+               goto end;
+       }
+
+       g_string_assign(output, "'");
+
+       for (ch = input; *ch != '\0'; ch++) {
+               if (*ch == '\'') {
+                       g_string_append(output, "'\"'\"'");
+               } else {
+                       g_string_append_c(output, *ch);
+               }
+       }
+
+       g_string_append_c(output, '\'');
+
+end:
+       return output;
+}
+
+BT_HIDDEN
+bool bt_common_string_is_printable(const char *input)
+{
+       const char *ch;
+       bool printable = true;
+       assert(input);
+
+       for (ch = input; *ch != '\0'; ch++) {
+               if (!isprint(*ch) && *ch != '\n' && *ch != '\r' &&
+                               *ch != '\t' && *ch != '\v') {
+                       printable = false;
+                       goto end;
+               }
+       }
+
+end:
+       return printable;
+}
+
+BT_HIDDEN
+void bt_common_destroy_lttng_live_url_parts(
+               struct bt_common_lttng_live_url_parts *parts)
+{
+       if (!parts) {
+               goto end;
+       }
+
+       if (parts->proto) {
+               g_string_free(parts->proto, TRUE);
+               parts->proto = NULL;
+       }
+
+       if (parts->hostname) {
+               g_string_free(parts->hostname, TRUE);
+               parts->hostname = NULL;
+       }
+
+       if (parts->target_hostname) {
+               g_string_free(parts->target_hostname, TRUE);
+               parts->target_hostname = NULL;
+       }
+
+       if (parts->session_name) {
+               g_string_free(parts->session_name, TRUE);
+               parts->session_name = NULL;
+       }
+
+end:
+       return;
+}
+
+BT_HIDDEN
+struct bt_common_lttng_live_url_parts bt_common_parse_lttng_live_url(
+               const char *url, char *error_buf, size_t error_buf_size)
+{
+       struct bt_common_lttng_live_url_parts parts;
+       const char *at = url;
+       size_t end_pos;
+
+       assert(url);
+       memset(&parts, 0, sizeof(parts));
+       parts.port = -1;
+
+       /* Protocol */
+       parts.proto = bt_common_string_until(at, "", ":", &end_pos);
+       if (!parts.proto || parts.proto->len == 0) {
+               if (error_buf) {
+                       snprintf(error_buf, error_buf_size, "Missing protocol");
+               }
+
+               goto error;
+       }
+
+       if (strcmp(parts.proto->str, "net") == 0) {
+               g_string_assign(parts.proto, "net4");
+       }
+
+       if (strcmp(parts.proto->str, "net4") != 0 &&
+                       strcmp(parts.proto->str, "net6") != 0) {
+               if (error_buf) {
+                       snprintf(error_buf, error_buf_size,
+                               "Unknown protocol: `%s`", parts.proto->str);
+               }
+
+               goto error;
+       }
+
+       if (at[end_pos] != ':') {
+               if (error_buf) {
+                       snprintf(error_buf, error_buf_size,
+                               "Expecting `:` after `%s`", parts.proto->str);
+               }
+
+               goto error;
+       }
+
+       at += end_pos;
+
+       /* :// */
+       if (strncmp(at, "://", 3) != 0) {
+               if (error_buf) {
+                       snprintf(error_buf, error_buf_size,
+                               "Expecting `://` after protocol");
+               }
+
+               goto error;
+       }
+
+       at += 3;
+
+       /* Hostname */
+       parts.hostname = bt_common_string_until(at, "", ":/", &end_pos);
+       if (!parts.hostname || parts.hostname->len == 0) {
+               if (error_buf) {
+                       snprintf(error_buf, error_buf_size, "Missing hostname");
+               }
+
+               goto error;
+       }
+
+       if (at[end_pos] == ':') {
+               /* Port */
+               GString *port;
+
+               at += end_pos + 1;
+               port = bt_common_string_until(at, "", "/", &end_pos);
+               if (!port || port->len == 0) {
+                       if (error_buf) {
+                               snprintf(error_buf, error_buf_size, "Missing port");
+                       }
+
+                       goto error;
+               }
+
+               if (sscanf(port->str, "%d", &parts.port) != 1) {
+                       if (error_buf) {
+                               snprintf(error_buf, error_buf_size,
+                                       "Invalid port: `%s`", port->str);
+                       }
+
+                       g_string_free(port, TRUE);
+                       goto error;
+               }
+
+               g_string_free(port, TRUE);
+
+               if (parts.port < 0 || parts.port >= 65536) {
+                       if (error_buf) {
+                               snprintf(error_buf, error_buf_size,
+                                       "Invalid port: %d", parts.port);
+                       }
+
+                       goto error;
+               }
+       }
+
+       if (at[end_pos] == '\0') {
+               goto end;
+       }
+
+       at += end_pos;
+
+       /* /host/ */
+       if (strncmp(at, "/host/", 6) != 0) {
+               if (error_buf) {
+                       snprintf(error_buf, error_buf_size,
+                               "Expecting `/host/` after hostname or port");
+               }
+
+               goto error;
+       }
+
+       at += 6;
+
+       /* Target hostname */
+       parts.target_hostname = bt_common_string_until(at, "", "/", &end_pos);
+       if (!parts.target_hostname || parts.target_hostname->len == 0) {
+               if (error_buf) {
+                       snprintf(error_buf, error_buf_size,
+                               "Missing target hostname");
+               }
+
+               goto error;
+       }
+
+       if (at[end_pos] == '\0') {
+               goto end;
+       }
+
+       at += end_pos + 1;
+
+       /* Session name */
+       parts.session_name = bt_common_string_until(at, "", "/", &end_pos);
+       if (!parts.session_name || parts.session_name->len == 0) {
+               if (error_buf) {
+                       snprintf(error_buf, error_buf_size,
+                               "Missing session name");
+               }
+
+               goto error;
+       }
+
+       if (at[end_pos] == '/') {
+               if (error_buf) {
+                       snprintf(error_buf, error_buf_size,
+                               "Unexpected `/` after session name (`%s`)",
+                               parts.session_name->str);
+               }
+
+               goto error;
+       }
+
+       goto end;
+
+error:
+       bt_common_destroy_lttng_live_url_parts(&parts);
+
+end:
+       return parts;
+}
This page took 0.030773 seconds and 4 git commands to generate.