1 /*
2 * Copyright (c) 2017 Oticon A/S
3 * Copyright (c) 2023 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <stdlib.h>
9 #include <stdio.h> /* for printfs */
10 #include <stdarg.h> /* for va args */
11 #include <unistd.h>
12 #include "nsi_tasks.h"
13 #include "nsi_cmdline.h"
14 #include "nsi_tracing.h"
15 #include "nsi_main.h"
16
17 /**
18 * Are stdout and stderr connected to a tty
19 * 0 = no
20 * 1 = yes
21 * -1 = we do not know yet
22 * Indexed 0:stdout, 1:stderr
23 */
24 static int is_a_tty[2] = {-1, -1};
25
26 #define ST_OUT 0
27 #define ST_ERR 1
28
decide_about_color(void)29 static void decide_about_color(void)
30 {
31 if (is_a_tty[0] == -1) {
32 is_a_tty[0] = isatty(STDOUT_FILENO);
33 }
34 if (is_a_tty[1] == -1) {
35 is_a_tty[1] = isatty(STDERR_FILENO);
36 }
37 }
38
39 #define ERROR 0
40 #define WARN 1
41 #define TRACE 2
42
43 static const char * const trace_type_esc_start[] = {
44 "\x1b[1;31m", /* ERROR - Foreground color = red, bold */
45 "\x1b[95m", /* WARNING - Foreground color = magenta */
46 "\x1b[0;39m", /* TRACE - reset all styles */
47 };
48
49 static const char trace_esc_end[] = "\x1b[0;39m"; /* Reset all styles */
50
nsi_vprint_warning(const char * format,va_list vargs)51 void nsi_vprint_warning(const char *format, va_list vargs)
52 {
53 if (is_a_tty[ST_ERR] == -1) {
54 decide_about_color();
55 }
56 if (is_a_tty[ST_ERR]) {
57 fprintf(stderr, "%s", trace_type_esc_start[WARN]);
58 }
59
60 vfprintf(stderr, format, vargs);
61
62 if (is_a_tty[ST_ERR]) {
63 fprintf(stderr, "%s", trace_esc_end);
64 }
65 }
66
nsi_vprint_error_and_exit(const char * format,va_list vargs)67 void nsi_vprint_error_and_exit(const char *format, va_list vargs)
68 {
69 if (is_a_tty[ST_ERR] == -1) {
70 decide_about_color();
71 }
72 if (is_a_tty[ST_ERR]) {
73 fprintf(stderr, "%s", trace_type_esc_start[ERROR]);
74 }
75
76 vfprintf(stderr, format, vargs);
77
78 if (is_a_tty[ST_ERR]) {
79 fprintf(stderr, "%s\n", trace_esc_end);
80 }
81
82 nsi_exit(1);
83 }
84
nsi_vprint_trace(const char * format,va_list vargs)85 void nsi_vprint_trace(const char *format, va_list vargs)
86 {
87 if (is_a_tty[ST_OUT] == -1) {
88 decide_about_color();
89 }
90 if (is_a_tty[ST_OUT]) {
91 fprintf(stdout, "%s", trace_type_esc_start[TRACE]);
92 }
93
94 vfprintf(stdout, format, vargs);
95
96 if (is_a_tty[ST_OUT]) {
97 fprintf(stdout, "%s", trace_esc_end);
98 }
99 }
100
trace_disable_color(char * argv,int offset)101 static void trace_disable_color(char *argv, int offset)
102 {
103 is_a_tty[0] = 0;
104 is_a_tty[1] = 0;
105 }
106
trace_enable_color(char * argv,int offset)107 static void trace_enable_color(char *argv, int offset)
108 {
109 is_a_tty[0] = -1;
110 is_a_tty[1] = -1;
111
112 }
113
trace_force_color(char * argv,int offset)114 static void trace_force_color(char *argv, int offset)
115 {
116 is_a_tty[0] = 1;
117 is_a_tty[1] = 1;
118 }
119
nsi_trace_over_tty(int file_number)120 int nsi_trace_over_tty(int file_number)
121 {
122 return is_a_tty[file_number];
123 }
124
125 NSI_TASK(decide_about_color, PRE_BOOT_2, 0);
126
nsi_add_tracing_options(void)127 static void nsi_add_tracing_options(void)
128 {
129 static struct args_struct_t trace_options[] = {
130 {
131 .is_switch = true,
132 .option = "color",
133 .type = 'b',
134 .call_when_found = trace_enable_color,
135 .descript = "(default) Enable color in traces if printing to console"
136 },
137 {
138 .is_switch = true,
139 .option = "no-color",
140 .type = 'b',
141 .call_when_found = trace_disable_color,
142 .descript = "Disable color in traces even if printing to console"
143 },
144 {
145 .is_switch = true,
146 .option = "force-color",
147 .type = 'b',
148 .call_when_found = trace_force_color,
149 .descript = "Enable color in traces even if printing to files/pipes"
150 },
151 ARG_TABLE_ENDMARKER
152 };
153
154 nsi_add_command_line_opts(trace_options);
155 }
156
157 NSI_TASK(nsi_add_tracing_options, PRE_BOOT_1, 0);
158