@@ -40,6 +40,8 @@ lib_libopenvswitch_la_SOURCES = \
lib/classifier-private.h \
lib/cmap.c \
lib/cmap.h \
+ lib/colors.c \
+ lib/colors.h \
lib/command-line.c \
lib/command-line.h \
lib/compiler.h \
new file mode 100644
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2016 6WIND S.A.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Handle color setup for output. */
+
+#include <config.h>
+
+#include "colors.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+struct color_key {
+ const char *name;
+ char **var_ptr;
+};
+
+/* Returns a pointer to the variable containing a given color. */
+static char **get_color(const struct color_key color_dic[], const char * name);
+
+/* Extract user-defined colors from OVS_COLORS environment variable. */
+static void colors_parse_from_env(const struct color_key color_dic[]);
+
+/* Global holder for colors. Declared in header file. */
+struct colors colors = { "", "", "", "", "", "", "", "" };
+
+static char **
+get_color(const struct color_key color_dic[], const char *name)
+{
+ const struct color_key *color;
+ for (color = color_dic; color->name; color++) {
+ if (!strcmp(color->name, name)) {
+ return color->var_ptr;
+ }
+ }
+ return NULL;
+}
+
+void
+colors_init(bool enable_color)
+{
+ /* If colored output is not enabled, just keep empty strings for color
+ * markers, including end marker.
+ */
+ if (!enable_color) {
+ return;
+ }
+
+ /* Color IDs to use in OVS_COLORS environment variable to overwrite
+ * defaults with custom colors.
+ */
+ const struct color_key color_dic[] =
+ {
+ { "ac", &(colors.actions) },
+ { "dr", &(colors.drop) },
+ { "le", &(colors.learn) },
+ { "pm", &(colors.param) },
+ { "pr", &(colors.paren) },
+ { "sp", &(colors.special) },
+ { "vl", &(colors.value) },
+ { NULL, NULL }
+ };
+
+ /* Actual color to use. First we define default values. */
+ colors.actions = "\33[1;31m\33[K"; /* bold red */
+ colors.drop = "\33[34m\33[K"; /* blue */
+ colors.learn = "\33[31m\33[K"; /* red */
+ colors.param = "\33[36m\33[K"; /* cyan */
+ colors.paren = "\33[35m\33[K"; /* magenta */
+ colors.special = "\33[33m\33[K"; /* yellow */
+ colors.value = "\33[32m\33[K"; /* green */
+ colors.end = "\33[m\33[K"; /* end marker */
+
+ /* Now, overwrite with user-defined color markers. */
+ colors_parse_from_env(color_dic);
+}
+
+/* Colorized output: get user-defined colors from OVS_COLORS environment
+ * variable. This must be a string of the form:
+ * ac=01;31:r=34:le=:pm=02;32:pr=01;30
+ * (see color_dic[] in colors_init() function for all color names)
+ * If a color is missing from this string, default value is used instead.
+ * If a color name is assigned an empty or incorrect value (i.e. something
+ * containing characters other than decimals and ';'), fields using this color
+ * will not be highlighted.
+ * If a color is assigned more than once, the last (rightmost) value appearing
+ * in the string is kept.
+ * Unknown color names are ignored so as to ensure forward compatibility.
+ * (Feeling adventurous? Try combining markers: "ac=1;3;5;7;38;2;30;150;100".)
+ */
+static void
+colors_parse_from_env(const struct color_key color_dic[])
+{
+ const char *color_str;
+ char *s;
+ char *token;
+
+ color_str = getenv("OVS_COLORS");
+ if (color_str == NULL || *color_str == '\0')
+ {
+ return;
+ }
+ s = xstrdup(color_str);
+
+ /* Loop on tokens: they are separated by columns ':' */
+ for (token = strsep(&s, ":");
+ token != NULL;
+ token = strsep(&s, ":")) {
+ char *ptr;
+ char *name = strsep(&token, "=");
+ for (ptr = token; ptr != NULL && *ptr != '\0'; ptr++) {
+ /* We accept only decimals and ';' for color marker */
+ if (*ptr == ';' || (*ptr >= '0' && *ptr <= '9')) {
+ continue;
+ }
+ name = NULL;
+ break;
+ }
+ if (name != NULL) {
+ /* We found a name and marker contains only decimals and ';'
+ * Try to get a pointer to associated color variable
+ */
+ char **color_var_ptr = get_color(color_dic, name);
+ /* If we know that color, update its value */
+ if (color_var_ptr != NULL) {
+ *color_var_ptr = malloc(sizeof(char)*(11 + strlen(token)));
+ sprintf(*color_var_ptr, "\33[%sm\33[K", token);
+ }
+ }
+ }
+}
new file mode 100644
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016 6WIND S.A.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COLORS_H
+#define COLORS_H 1
+
+#include <stdbool.h>
+
+struct colors {
+ /* Color codes for various situation. Each of these is a fully formed
+ * Select Graphic Rendition (SGR, "\33[...m") start string for the
+ * appropriate color.
+ */
+ char *actions;
+ char *drop;
+ char *learn;
+ char *param;
+ char *paren;
+ char *special;
+ char *value;
+
+ /* SGR end string. */
+ char *end;
+};
+extern struct colors colors;
+
+void colors_init(bool enable_color);
+
+#endif /* colors.h */
@@ -33,6 +33,7 @@
#include "classifier.h"
#include "command-line.h"
#include "daemon.h"
+#include "colors.h"
#include "compiler.h"
#include "dirs.h"
#include "dynamic-string.h"
@@ -367,6 +368,8 @@ parse_options(int argc, char *argv[])
allowed_protocols &= version_protocols;
mask_allowed_ofp_versions(ofputil_protocols_to_version_bitmap(
allowed_protocols));
+
+ colors_init(enable_color);
}
static void
OVS_COLORS environment variable is parsed to extract user-defined preferences regarding colors (this is used to set up a color theme, not to replace the `--color` option for activating color output). The string should be of a format similar to LS_COLORS or GREP_COLORS, with available colors being as follows: * ac: action field * dr: drop keyword * le: learn keyword * pm: parameters receiving attributes * pr: keyword having parenthesis * sp: some special keywords * vl: lone values with no parameter name For color whose idendifier does not appear in the string, the default hardcoded value is used instead. As an example, setting OVS_COLORS to the following string is equivalent to using the default values: OVS_COLORS="ac:01;31:dr=34:le=31:pm=36:pr=35:sp=33:vl=32" Signed-off-by: Quentin Monnet <quentin.monnet@6wind.com> --- lib/automake.mk | 2 + lib/colors.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/colors.h | 42 +++++++++++++++ utilities/ovs-ofctl.c | 3 ++ 4 files changed, 193 insertions(+) create mode 100644 lib/colors.c create mode 100644 lib/colors.h