]>
Commit | Line | Data |
---|---|---|
ef7b593b QM |
1 | /* |
2 | * Copyright (c) 2016 6WIND S.A. | |
3 | * | |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
7 | * | |
8 | * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
15 | */ | |
16 | ||
17 | /* Handle color setup for output. */ | |
18 | ||
19 | #include <config.h> | |
20 | ||
21 | #include "colors.h" | |
22 | ||
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | ||
26 | #include "util.h" | |
27 | ||
28 | struct color_key { | |
29 | const char *name; | |
30 | char **var_ptr; | |
31 | }; | |
32 | ||
33 | /* Returns a pointer to the variable containing a given color. */ | |
34 | static char **get_color(const struct color_key color_dic[], const char * name); | |
35 | ||
36 | /* Extract user-defined colors from OVS_COLORS environment variable. */ | |
37 | static void colors_parse_from_env(const struct color_key color_dic[]); | |
38 | ||
39 | /* Global holder for colors. Declared in header file. */ | |
40 | struct colors colors = { "", "", "", "", "", "", "", "" }; | |
41 | ||
42 | static char ** | |
43 | get_color(const struct color_key color_dic[], const char *name) | |
44 | { | |
45 | const struct color_key *color; | |
46 | for (color = color_dic; color->name; color++) { | |
47 | if (!strcmp(color->name, name)) { | |
48 | return color->var_ptr; | |
49 | } | |
50 | } | |
51 | return NULL; | |
52 | } | |
53 | ||
54 | void | |
55 | colors_init(bool enable_color) | |
56 | { | |
57 | /* If colored output is not enabled, just keep empty strings for color | |
58 | * markers, including end marker. | |
59 | */ | |
60 | if (!enable_color) { | |
61 | return; | |
62 | } | |
63 | ||
64 | /* Color IDs to use in OVS_COLORS environment variable to overwrite | |
65 | * defaults with custom colors. | |
66 | */ | |
67 | const struct color_key color_dic[] = { | |
68 | { "ac", &colors.actions }, | |
69 | { "dr", &colors.drop }, | |
70 | { "le", &colors.learn }, | |
71 | { "pm", &colors.param }, | |
72 | { "pr", &colors.paren }, | |
73 | { "sp", &colors.special }, | |
74 | { "vl", &colors.value }, | |
75 | { NULL, NULL } | |
76 | }; | |
77 | ||
78 | /* Actual color to use. First we define default values. */ | |
79 | colors.actions = "\33[1;31m\33[K"; /* bold red */ | |
80 | colors.drop = "\33[34m\33[K"; /* blue */ | |
81 | colors.learn = "\33[31m\33[K"; /* red */ | |
82 | colors.param = "\33[36m\33[K"; /* cyan */ | |
83 | colors.paren = "\33[35m\33[K"; /* magenta */ | |
84 | colors.special = "\33[33m\33[K"; /* yellow */ | |
85 | colors.value = "\33[32m\33[K"; /* green */ | |
86 | colors.end = "\33[m\33[K"; /* end marker */ | |
87 | ||
88 | /* Now, overwrite with user-defined color markers. */ | |
89 | colors_parse_from_env(color_dic); | |
90 | } | |
91 | ||
92 | /* Colorized output: get user-defined colors from OVS_COLORS environment | |
93 | * variable. This must be a string of the form: | |
94 | * ac=01;31:r=34:le=:pm=02;32:pr=01;30 | |
95 | * (see color_dic[] in colors_init() function for all color names) | |
96 | * If a color is missing from this string, default value is used instead. | |
97 | * If a color name is assigned an empty or incorrect value (i.e. something | |
98 | * containing characters other than decimals and ';'), fields using this color | |
99 | * will not be highlighted. | |
100 | * If a color is assigned more than once, the last (rightmost) value appearing | |
101 | * in the string is kept. | |
102 | * Unknown color names are ignored so as to ensure forward compatibility. | |
103 | * (Feeling adventurous? Try combining markers: "ac=1;3;5;7;38;2;30;150;100".) | |
104 | */ | |
105 | static void | |
106 | colors_parse_from_env(const struct color_key color_dic[]) | |
107 | { | |
108 | const char *color_str = getenv("OVS_COLORS"); | |
109 | if (color_str == NULL || *color_str == '\0') { | |
110 | return; | |
111 | } | |
112 | ||
113 | /* Loop on tokens: they are separated by columns ':' */ | |
114 | char *s = xstrdup(color_str); | |
7b398b07 | 115 | char *s_head = s; |
ef7b593b QM |
116 | for (char *token = strsep(&s, ":"); |
117 | token != NULL; | |
118 | token = strsep(&s, ":")) { | |
119 | char *name = strsep(&token, "="); | |
120 | for (char *ptr = token; ptr != NULL && *ptr != '\0'; ptr++) { | |
121 | /* We accept only decimals and ';' for color marker. */ | |
122 | if (*ptr == ';' || (*ptr >= '0' && *ptr <= '9')) { | |
123 | continue; | |
124 | } | |
125 | name = NULL; | |
126 | break; | |
127 | } | |
128 | if (name != NULL) { | |
129 | /* We found a name and marker contains only decimals and ';'. | |
130 | * Try to get a pointer to associated color variable. */ | |
131 | char **color_var_ptr = get_color(color_dic, name); | |
132 | /* If we know that color, update its value. */ | |
133 | if (color_var_ptr != NULL) { | |
134 | *color_var_ptr = xasprintf("\33[%sm\33[K", token); | |
135 | } | |
136 | } | |
137 | } | |
7b398b07 | 138 | free(s_head); |
ef7b593b | 139 | } |