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