]> git.proxmox.com Git - mirror_iproute2.git/blob - lib/color.c
eaf69e74d673a6e949e68c504d54777927789b79
[mirror_iproute2.git] / lib / color.c
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 int color_fprintf(FILE *fp, enum color_attr attr, const char *fmt, ...)
136 {
137 int ret = 0;
138 va_list args;
139
140 va_start(args, fmt);
141
142 if (!color_is_enabled || attr == COLOR_NONE) {
143 ret = vfprintf(fp, fmt, args);
144 goto end;
145 }
146
147 ret += fprintf(fp, "%s", color_codes[is_dark_bg ?
148 attr_colors_dark[attr] : attr_colors_light[attr]]);
149
150 ret += vfprintf(fp, fmt, args);
151 ret += fprintf(fp, "%s", color_codes[C_CLEAR]);
152
153 end:
154 va_end(args);
155 return ret;
156 }
157
158 enum color_attr ifa_family_color(__u8 ifa_family)
159 {
160 switch (ifa_family) {
161 case AF_INET:
162 return COLOR_INET;
163 case AF_INET6:
164 return COLOR_INET6;
165 default:
166 return COLOR_NONE;
167 }
168 }
169
170 enum color_attr oper_state_color(__u8 state)
171 {
172 switch (state) {
173 case IF_OPER_UP:
174 return COLOR_OPERSTATE_UP;
175 case IF_OPER_DOWN:
176 return COLOR_OPERSTATE_DOWN;
177 default:
178 return COLOR_NONE;
179 }
180 }