]>
Commit | Line | Data |
---|---|---|
1 | /* SPDX-License-Identifier: GPL-2.0 */ | |
2 | #include <stdio.h> | |
3 | #include <stdarg.h> | |
4 | #include <stdlib.h> | |
5 | #include <string.h> | |
6 | #include <unistd.h> | |
7 | #include <sys/socket.h> | |
8 | #include <sys/types.h> | |
9 | #include <linux/if.h> | |
10 | ||
11 | #include "color.h" | |
12 | #include "utils.h" | |
13 | ||
14 | enum color { | |
15 | C_RED, | |
16 | C_GREEN, | |
17 | C_YELLOW, | |
18 | C_BLUE, | |
19 | C_MAGENTA, | |
20 | C_CYAN, | |
21 | C_WHITE, | |
22 | C_BOLD_RED, | |
23 | C_BOLD_GREEN, | |
24 | C_BOLD_YELLOW, | |
25 | C_BOLD_BLUE, | |
26 | C_BOLD_MAGENTA, | |
27 | C_BOLD_CYAN, | |
28 | C_BOLD_WHITE, | |
29 | C_CLEAR | |
30 | }; | |
31 | ||
32 | static const char * const color_codes[] = { | |
33 | "\e[31m", | |
34 | "\e[32m", | |
35 | "\e[33m", | |
36 | "\e[34m", | |
37 | "\e[35m", | |
38 | "\e[36m", | |
39 | "\e[37m", | |
40 | "\e[1;31m", | |
41 | "\e[1;32m", | |
42 | "\e[1;33m", | |
43 | "\e[1;34m", | |
44 | "\e[1;35m", | |
45 | "\e[1;36m", | |
46 | "\e[1;37m", | |
47 | "\e[0m", | |
48 | NULL, | |
49 | }; | |
50 | ||
51 | /* light background */ | |
52 | static enum color attr_colors_light[] = { | |
53 | C_CYAN, | |
54 | C_YELLOW, | |
55 | C_MAGENTA, | |
56 | C_BLUE, | |
57 | C_GREEN, | |
58 | C_RED, | |
59 | C_CLEAR, | |
60 | }; | |
61 | ||
62 | /* dark background */ | |
63 | static enum color attr_colors_dark[] = { | |
64 | C_BOLD_CYAN, | |
65 | C_BOLD_YELLOW, | |
66 | C_BOLD_MAGENTA, | |
67 | C_BOLD_BLUE, | |
68 | C_BOLD_GREEN, | |
69 | C_BOLD_RED, | |
70 | C_CLEAR | |
71 | }; | |
72 | ||
73 | static int is_dark_bg; | |
74 | static int color_is_enabled; | |
75 | ||
76 | void enable_color(void) | |
77 | { | |
78 | color_is_enabled = 1; | |
79 | set_color_palette(); | |
80 | } | |
81 | ||
82 | bool check_enable_color(int color, int json) | |
83 | { | |
84 | if (json || color == COLOR_OPT_NEVER) | |
85 | return false; | |
86 | ||
87 | if (color == COLOR_OPT_ALWAYS || isatty(fileno(stdout))) { | |
88 | enable_color(); | |
89 | return true; | |
90 | } | |
91 | return false; | |
92 | } | |
93 | ||
94 | bool matches_color(const char *arg, int *val) | |
95 | { | |
96 | char *dup, *p; | |
97 | ||
98 | if (!val) | |
99 | return false; | |
100 | ||
101 | dup = strdupa(arg); | |
102 | p = strchrnul(dup, '='); | |
103 | if (*p) | |
104 | *(p++) = '\0'; | |
105 | ||
106 | if (matches(dup, "-color")) | |
107 | return false; | |
108 | ||
109 | if (*p == '\0' || !strcmp(p, "always")) | |
110 | *val = COLOR_OPT_ALWAYS; | |
111 | else if (!strcmp(p, "auto")) | |
112 | *val = COLOR_OPT_AUTO; | |
113 | else if (!strcmp(p, "never")) | |
114 | *val = COLOR_OPT_NEVER; | |
115 | else | |
116 | return false; | |
117 | return true; | |
118 | } | |
119 | ||
120 | void set_color_palette(void) | |
121 | { | |
122 | char *p = getenv("COLORFGBG"); | |
123 | ||
124 | /* | |
125 | * COLORFGBG environment variable usually contains either two or three | |
126 | * values separated by semicolons; we want the last value in either case. | |
127 | * If this value is 0-6 or 8, background is dark. | |
128 | */ | |
129 | if (p && (p = strrchr(p, ';')) != NULL | |
130 | && ((p[1] >= '0' && p[1] <= '6') || p[1] == '8') | |
131 | && p[2] == '\0') | |
132 | is_dark_bg = 1; | |
133 | } | |
134 | ||
135 | __attribute__((format(printf, 3, 4))) | |
136 | int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...) | |
137 | { | |
138 | int ret = 0; | |
139 | va_list args; | |
140 | ||
141 | va_start(args, fmt); | |
142 | ||
143 | if (!color_is_enabled || attr == COLOR_NONE) { | |
144 | ret = vfprintf(fp, fmt, args); | |
145 | goto end; | |
146 | } | |
147 | ||
148 | ret += fprintf(fp, "%s", color_codes[is_dark_bg ? | |
149 | attr_colors_dark[attr] : attr_colors_light[attr]]); | |
150 | ||
151 | ret += vfprintf(fp, fmt, args); | |
152 | ret += fprintf(fp, "%s", color_codes[C_CLEAR]); | |
153 | ||
154 | end: | |
155 | va_end(args); | |
156 | return ret; | |
157 | } | |
158 | ||
159 | enum color_attr ifa_family_color(__u8 ifa_family) | |
160 | { | |
161 | switch (ifa_family) { | |
162 | case AF_INET: | |
163 | return COLOR_INET; | |
164 | case AF_INET6: | |
165 | return COLOR_INET6; | |
166 | default: | |
167 | return COLOR_NONE; | |
168 | } | |
169 | } | |
170 | ||
171 | enum color_attr oper_state_color(__u8 state) | |
172 | { | |
173 | switch (state) { | |
174 | case IF_OPER_UP: | |
175 | return COLOR_OPERSTATE_UP; | |
176 | case IF_OPER_DOWN: | |
177 | return COLOR_OPERSTATE_DOWN; | |
178 | default: | |
179 | return COLOR_NONE; | |
180 | } | |
181 | } |