]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wireguard-tools/terminal.c
zfs: merge openzfs/zfs@dbda45160
[FreeBSD/FreeBSD.git] / contrib / wireguard-tools / terminal.c
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /*
3  * Copyright (C) 2015-2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
4  */
5
6 #include <stdarg.h>
7 #include <stddef.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdbool.h>
12 #include <unistd.h>
13 #include "ctype.h"
14 #include "terminal.h"
15
16 static bool color_mode(void)
17 {
18         static int mode = -1;
19         const char *var;
20
21         if (mode != -1)
22                 return mode;
23         var = getenv("WG_COLOR_MODE");
24         if (var && !strcmp(var, "always"))
25                 mode = true;
26         else if (var && !strcmp(var, "never"))
27                 mode = false;
28         else
29                 mode = isatty(fileno(stdout));
30         return mode;
31 }
32
33 static void filter_ansi(const char *fmt, va_list args)
34 {
35         char *str = NULL;
36         size_t len, i, j;
37
38         if (color_mode()) {
39                 vfprintf(stdout, fmt, args);
40                 return;
41         }
42
43         len = vasprintf(&str, fmt, args);
44
45         if (len >= 2) {
46                 for (i = 0; i < len - 2; ++i) {
47                         if (str[i] == '\x1b' && str[i + 1] == '[') {
48                                 str[i] = str[i + 1] = '\0';
49                                 for (j = i + 2; j < len; ++j) {
50                                         if (char_is_alpha(str[j]))
51                                                 break;
52                                         str[j] = '\0';
53                                 }
54                                 str[j] = '\0';
55                         }
56                 }
57         }
58         for (i = 0; i < len; i = j) {
59                 fputs(&str[i], stdout);
60                 for (j = i + strlen(&str[i]); j < len; ++j) {
61                         if (str[j] != '\0')
62                                 break;
63                 }
64         }
65
66         free(str);
67 }
68
69 void terminal_printf(const char *fmt, ...)
70 {
71         va_list args;
72
73         va_start(args, fmt);
74         filter_ansi(fmt, args);
75         va_end(args);
76 }