1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 #pragma once
3
4 #include <stdarg.h>
5 #include <stdbool.h>
6 #include <stdio.h>
7 #include <syslog.h>
8 #include <sys/types.h>
9
10 #include "macro.h"
11 #include "time-util.h"
12
13 /* Regular colors */
14 #define ANSI_BLACK "\x1B[0;30m" /* Some type of grey usually. */
15 #define ANSI_RED "\x1B[0;31m"
16 #define ANSI_GREEN "\x1B[0;32m"
17 #define ANSI_YELLOW "\x1B[0;33m"
18 #define ANSI_BLUE "\x1B[0;34m"
19 #define ANSI_MAGENTA "\x1B[0;35m"
20 #define ANSI_CYAN "\x1B[0;36m"
21 #define ANSI_WHITE "\x1B[0;37m" /* This is actually rendered as light grey, legible even on a white
22 * background. See ANSI_HIGHLIGHT_WHITE for real white. */
23
24 #define ANSI_BRIGHT_BLACK "\x1B[0;90m"
25 #define ANSI_BRIGHT_RED "\x1B[0;91m"
26 #define ANSI_BRIGHT_GREEN "\x1B[0;92m"
27 #define ANSI_BRIGHT_YELLOW "\x1B[0;93m"
28 #define ANSI_BRIGHT_BLUE "\x1B[0;94m"
29 #define ANSI_BRIGHT_MAGENTA "\x1B[0;95m"
30 #define ANSI_BRIGHT_CYAN "\x1B[0;96m"
31 #define ANSI_BRIGHT_WHITE "\x1B[0;97m"
32
33 #define ANSI_GREY "\x1B[0;38;5;245m"
34
35 /* Bold/highlighted */
36 #define ANSI_HIGHLIGHT_BLACK "\x1B[0;1;30m"
37 #define ANSI_HIGHLIGHT_RED "\x1B[0;1;31m"
38 #define ANSI_HIGHLIGHT_GREEN "\x1B[0;1;32m"
39 #define _ANSI_HIGHLIGHT_YELLOW "\x1B[0;1;33m" /* This yellow is currently not displayed well by some terminals */
40 #define ANSI_HIGHLIGHT_BLUE "\x1B[0;1;34m"
41 #define ANSI_HIGHLIGHT_MAGENTA "\x1B[0;1;35m"
42 #define ANSI_HIGHLIGHT_CYAN "\x1B[0;1;36m"
43 #define ANSI_HIGHLIGHT_WHITE "\x1B[0;1;37m"
44 #define ANSI_HIGHLIGHT_YELLOW4 "\x1B[0;1;38;5;100m"
45 #define ANSI_HIGHLIGHT_KHAKI3 "\x1B[0;1;38;5;185m"
46 #define ANSI_HIGHLIGHT_GREY "\x1B[0;1;38;5;245m"
47
48 #define ANSI_HIGHLIGHT_YELLOW ANSI_HIGHLIGHT_KHAKI3 /* Replacement yellow that is more legible */
49
50 /* Underlined */
51 #define ANSI_GREY_UNDERLINE "\x1B[0;4;38;5;245m"
52 #define ANSI_HIGHLIGHT_RED_UNDERLINE "\x1B[0;1;4;31m"
53 #define ANSI_HIGHLIGHT_GREEN_UNDERLINE "\x1B[0;1;4;32m"
54 #define ANSI_HIGHLIGHT_YELLOW_UNDERLINE "\x1B[0;1;4;38;5;185m"
55 #define ANSI_HIGHLIGHT_BLUE_UNDERLINE "\x1B[0;1;4;34m"
56 #define ANSI_HIGHLIGHT_MAGENTA_UNDERLINE "\x1B[0;1;4;35m"
57 #define ANSI_HIGHLIGHT_GREY_UNDERLINE "\x1B[0;1;4;38;5;245m"
58
59 /* Other ANSI codes */
60 #define ANSI_UNDERLINE "\x1B[0;4m"
61 #define ANSI_HIGHLIGHT "\x1B[0;1;39m"
62 #define ANSI_HIGHLIGHT_UNDERLINE "\x1B[0;1;4m"
63
64 /* Fallback colors: 256 -> 16 */
65 #define ANSI_HIGHLIGHT_GREY_FALLBACK "\x1B[0;1;90m"
66 #define ANSI_HIGHLIGHT_YELLOW_FALLBACK "\x1B[0;1;33m"
67
68 /* Reset/clear ANSI styles */
69 #define ANSI_NORMAL "\x1B[0m"
70
71 /* Erase characters until the end of the line */
72 #define ANSI_ERASE_TO_END_OF_LINE "\x1B[K"
73
74 /* Move cursor up one line */
75 #define ANSI_REVERSE_LINEFEED "\x1BM"
76
77 /* Set cursor to top left corner and clear screen */
78 #define ANSI_HOME_CLEAR "\x1B[H\x1B[2J"
79
80 int reset_terminal_fd(int fd, bool switch_to_text);
81 int reset_terminal(const char *name);
82
83 int open_terminal(const char *name, int mode);
84
85 /* Flags for tweaking the way we become the controlling process of a terminal. */
86 typedef enum AcquireTerminalFlags {
87 /* Try to become the controlling process of the TTY. If we can't return -EPERM. */
88 ACQUIRE_TERMINAL_TRY = 0,
89
90 /* Tell the kernel to forcibly make us the controlling process of the TTY. Returns -EPERM if the kernel doesn't allow that. */
91 ACQUIRE_TERMINAL_FORCE = 1,
92
93 /* If we can't become the controlling process of the TTY right-away, then wait until we can. */
94 ACQUIRE_TERMINAL_WAIT = 2,
95
96 /* Pick one of the above, and then OR this flag in, in order to request permissive behaviour, if we can't become controlling process then don't mind */
97 ACQUIRE_TERMINAL_PERMISSIVE = 1 << 2,
98 } AcquireTerminalFlags;
99
100 /* Limits the use of ANSI colors to a subset. */
101 typedef enum ColorMode {
102 /* No colors, monochrome output. */
103 COLOR_OFF,
104
105 /* All colors, no restrictions. */
106 COLOR_ON,
107
108 /* Only the base 16 colors. */
109 COLOR_16,
110
111 /* Only 256 colors. */
112 COLOR_256,
113
114 /* For truecolor or 24bit color support.*/
115 COLOR_24BIT,
116
117 _COLOR_INVALID = -EINVAL,
118 } ColorMode;
119
120 int acquire_terminal(const char *name, AcquireTerminalFlags flags, usec_t timeout);
121 int release_terminal(void);
122
123 int terminal_vhangup_fd(int fd);
124 int terminal_vhangup(const char *name);
125
126 int terminal_set_size_fd(int fd, const char *ident, unsigned rows, unsigned cols);
127
128 int chvt(int vt);
129
130 int read_one_char(FILE *f, char *ret, usec_t timeout, bool *need_nl);
131 int ask_char(char *ret, const char *replies, const char *text, ...) _printf_(3, 4);
132 int ask_string(char **ret, const char *text, ...) _printf_(2, 3);
133
134 int vt_disallocate(const char *name);
135
136 int resolve_dev_console(char **ret);
137 int get_kernel_consoles(char ***ret);
138 bool tty_is_vc(const char *tty);
139 bool tty_is_vc_resolve(const char *tty);
140 bool tty_is_console(const char *tty) _pure_;
141 int vtnr_from_tty(const char *tty);
142 const char *default_term_for_tty(const char *tty);
143
144 int make_console_stdio(void);
145
146 int fd_columns(int fd);
147 unsigned columns(void);
148 int fd_lines(int fd);
149 unsigned lines(void);
150
151 void columns_lines_cache_reset(int _unused_ signum);
152 void reset_terminal_feature_caches(void);
153
154 bool on_tty(void);
155 bool terminal_is_dumb(void);
156 ColorMode get_color_mode(void);
157 bool underline_enabled(void);
158 bool dev_console_colors_enabled(void);
159
colors_enabled(void)160 static inline bool colors_enabled(void) {
161
162 /* Returns true if colors are considered supported on our stdout. */
163 return get_color_mode() != COLOR_OFF;
164 }
165
166 #define DEFINE_ANSI_FUNC(name, NAME) \
167 static inline const char *ansi_##name(void) { \
168 return colors_enabled() ? ANSI_##NAME : ""; \
169 }
170
171 #define DEFINE_ANSI_FUNC_256(name, NAME, FALLBACK) \
172 static inline const char *ansi_##name(void) { \
173 switch (get_color_mode()) { \
174 case COLOR_OFF: return ""; \
175 case COLOR_16: return ANSI_##FALLBACK; \
176 default : return ANSI_##NAME; \
177 } \
178 }
179
180 #define DEFINE_ANSI_FUNC_UNDERLINE(name, NAME) \
181 static inline const char *ansi_##name(void) { \
182 return underline_enabled() ? ANSI_##NAME ANSI_UNDERLINE : \
183 colors_enabled() ? ANSI_##NAME : ""; \
184 }
185
186
187 #define DEFINE_ANSI_FUNC_UNDERLINE_256(name, NAME, FALLBACK) \
188 static inline const char *ansi_##name(void) { \
189 switch (get_color_mode()) { \
190 case COLOR_OFF: return ""; \
191 case COLOR_16: return underline_enabled() ? ANSI_##FALLBACK ANSI_UNDERLINE : ANSI_##FALLBACK; \
192 default : return underline_enabled() ? ANSI_##NAME ANSI_UNDERLINE: ANSI_##NAME; \
193 } \
194 }
195
196 DEFINE_ANSI_FUNC(normal, NORMAL);
197 DEFINE_ANSI_FUNC(highlight, HIGHLIGHT);
198 DEFINE_ANSI_FUNC(black, BLACK);
199 DEFINE_ANSI_FUNC(red, RED);
200 DEFINE_ANSI_FUNC(green, GREEN);
201 DEFINE_ANSI_FUNC(yellow, YELLOW);
202 DEFINE_ANSI_FUNC(blue, BLUE);
203 DEFINE_ANSI_FUNC(magenta, MAGENTA);
204 DEFINE_ANSI_FUNC(cyan, CYAN);
205 DEFINE_ANSI_FUNC(white, WHITE);
206 DEFINE_ANSI_FUNC_256(grey, GREY, BRIGHT_BLACK);
207
208 DEFINE_ANSI_FUNC(bright_black, BRIGHT_BLACK);
209 DEFINE_ANSI_FUNC(bright_red, BRIGHT_RED);
210 DEFINE_ANSI_FUNC(bright_green, BRIGHT_GREEN);
211 DEFINE_ANSI_FUNC(bright_yellow, BRIGHT_YELLOW);
212 DEFINE_ANSI_FUNC(bright_blue, BRIGHT_BLUE);
213 DEFINE_ANSI_FUNC(bright_magenta, BRIGHT_MAGENTA);
214 DEFINE_ANSI_FUNC(bright_cyan, BRIGHT_CYAN);
215 DEFINE_ANSI_FUNC(bright_white, BRIGHT_WHITE);
216
217 DEFINE_ANSI_FUNC(highlight_black, HIGHLIGHT_BLACK);
218 DEFINE_ANSI_FUNC(highlight_red, HIGHLIGHT_RED);
219 DEFINE_ANSI_FUNC(highlight_green, HIGHLIGHT_GREEN);
220 DEFINE_ANSI_FUNC_256(highlight_yellow, HIGHLIGHT_YELLOW, HIGHLIGHT_YELLOW_FALLBACK);
221 DEFINE_ANSI_FUNC_256(highlight_yellow4, HIGHLIGHT_YELLOW4, HIGHLIGHT_YELLOW_FALLBACK);
222 DEFINE_ANSI_FUNC(highlight_blue, HIGHLIGHT_BLUE);
223 DEFINE_ANSI_FUNC(highlight_magenta, HIGHLIGHT_MAGENTA);
224 DEFINE_ANSI_FUNC(highlight_cyan, HIGHLIGHT_CYAN);
225 DEFINE_ANSI_FUNC_256(highlight_grey, HIGHLIGHT_GREY, HIGHLIGHT_GREY_FALLBACK);
226 DEFINE_ANSI_FUNC(highlight_white, HIGHLIGHT_WHITE);
227
_ansi_highlight_yellow(void)228 static inline const char* _ansi_highlight_yellow(void) {
229 return colors_enabled() ? _ANSI_HIGHLIGHT_YELLOW : "";
230 }
231
232 DEFINE_ANSI_FUNC_UNDERLINE(underline, NORMAL);
233 DEFINE_ANSI_FUNC_UNDERLINE(highlight_underline, HIGHLIGHT);
234 DEFINE_ANSI_FUNC_UNDERLINE_256(grey_underline, GREY, BRIGHT_BLACK);
235 DEFINE_ANSI_FUNC_UNDERLINE(highlight_red_underline, HIGHLIGHT_RED);
236 DEFINE_ANSI_FUNC_UNDERLINE(highlight_green_underline, HIGHLIGHT_GREEN);
237 DEFINE_ANSI_FUNC_UNDERLINE_256(highlight_yellow_underline, HIGHLIGHT_YELLOW, HIGHLIGHT_YELLOW_FALLBACK);
238 DEFINE_ANSI_FUNC_UNDERLINE(highlight_blue_underline, HIGHLIGHT_BLUE);
239 DEFINE_ANSI_FUNC_UNDERLINE(highlight_magenta_underline, HIGHLIGHT_MAGENTA);
240 DEFINE_ANSI_FUNC_UNDERLINE_256(highlight_grey_underline, HIGHLIGHT_GREY, HIGHLIGHT_GREY_FALLBACK);
241
242 int get_ctty_devnr(pid_t pid, dev_t *d);
243 int get_ctty(pid_t, dev_t *_devnr, char **r);
244
245 int getttyname_malloc(int fd, char **r);
246 int getttyname_harder(int fd, char **r);
247
248 int ptsname_malloc(int fd, char **ret);
249
250 int openpt_allocate(int flags, char **ret_slave);
251 int openpt_allocate_in_namespace(pid_t pid, int flags, char **ret_slave);
252 int open_terminal_in_namespace(pid_t pid, const char *name, int mode);
253
254 int vt_default_utf8(void);
255 int vt_reset_keyboard(int fd);
256 int vt_restore(int fd);
257 int vt_release(int fd, bool restore_vt);
258
259 void get_log_colors(int priority, const char **on, const char **off, const char **highlight);
260
ansi_highlight_green_red(bool b)261 static inline const char* ansi_highlight_green_red(bool b) {
262 return b ? ansi_highlight_green() : ansi_highlight_red();
263 }
264
265 /* This assumes there is a 'tty' group */
266 #define TTY_MODE 0620
267