Wed Jan 8 2020 09:49:51

Asterisk developer's documentation


term.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2010, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Terminal Routines
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
33 
34 #include "asterisk/_private.h"
35 #include <sys/time.h>
36 #include <signal.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 
40 #include "asterisk/term.h"
41 #include "asterisk/lock.h"
42 #include "asterisk/utils.h"
43 
44 static int vt100compat;
45 
46 static char prepdata[80] = "";
47 static char enddata[80] = "";
48 static char quitdata[80] = "";
49 
50 static const char * const termpath[] = {
51  "/usr/share/terminfo",
52  "/usr/local/share/misc/terminfo",
53  "/usr/lib/terminfo",
54  NULL
55  };
56 
57 static int opposite(int color)
58 {
59  int lookup[] = {
60  /* BLACK */ COLOR_BLACK,
61  /* RED */ COLOR_MAGENTA,
62  /* GREEN */ COLOR_GREEN,
63  /* BROWN */ COLOR_BROWN,
64  /* BLUE */ COLOR_CYAN,
65  /* MAGENTA */ COLOR_RED,
66  /* CYAN */ COLOR_BLUE,
67  /* WHITE */ COLOR_BLACK };
68  return color ? lookup[color - 30] : 0;
69 }
70 
71 /* Ripped off from Ross Ridge, but it's public domain code (libmytinfo) */
72 static short convshort(char *s)
73 {
74  register int a, b;
75 
76  a = (int) s[0] & 0377;
77  b = (int) s[1] & 0377;
78 
79  if (a == 0377 && b == 0377)
80  return -1;
81  if (a == 0376 && b == 0377)
82  return -2;
83 
84  return a + b * 256;
85 }
86 
87 int ast_term_init(void)
88 {
89  char *term = getenv("TERM");
90  char termfile[256] = "";
91  char buffer[512] = "";
92  int termfd = -1, parseokay = 0, i;
93 
94  if (ast_opt_no_color) {
95  return 0;
96  }
97 
98  if (!ast_opt_console) {
99  /* If any remote console is not compatible, we'll strip the color codes at that point */
100  vt100compat = 1;
101  goto end;
102  }
103 
104  if (!term) {
105  return 0;
106  }
107 
108  for (i = 0;; i++) {
109  if (termpath[i] == NULL) {
110  break;
111  }
112  snprintf(termfile, sizeof(termfile), "%s/%c/%s", termpath[i], *term, term);
113  termfd = open(termfile, O_RDONLY);
114  if (termfd > -1) {
115  break;
116  }
117  }
118  if (termfd > -1) {
119  int actsize = read(termfd, buffer, sizeof(buffer) - 1);
120  short sz_names = convshort(buffer + 2);
121  short sz_bools = convshort(buffer + 4);
122  short n_nums = convshort(buffer + 6);
123 
124  /* if ((sz_names + sz_bools) & 1)
125  sz_bools++; */
126 
127  if (sz_names + sz_bools + n_nums < actsize) {
128  /* Offset 13 is defined in /usr/include/term.h, though we do not
129  * include it here, as it conflicts with include/asterisk/term.h */
130  short max_colors = convshort(buffer + 12 + sz_names + sz_bools + 13 * 2);
131  if (max_colors > 0) {
132  vt100compat = 1;
133  }
134  parseokay = 1;
135  }
136  close(termfd);
137  }
138 
139  if (!parseokay) {
140  /* These comparisons should not be substrings nor case-insensitive, as
141  * terminal types are very particular about how they treat suffixes and
142  * capitalization. For example, terminal type 'linux-m' does NOT
143  * support color, while 'linux' does. Not even all vt100* terminals
144  * support color, either (e.g. 'vt100+fnkeys'). */
145  if (!strcmp(term, "linux")) {
146  vt100compat = 1;
147  } else if (!strcmp(term, "xterm")) {
148  vt100compat = 1;
149  } else if (!strcmp(term, "xterm-color")) {
150  vt100compat = 1;
151  } else if (!strcmp(term, "xterm-256color")) {
152  vt100compat = 1;
153  } else if (!strncmp(term, "Eterm", 5)) {
154  /* Both entries which start with Eterm support color */
155  vt100compat = 1;
156  } else if (!strcmp(term, "vt100")) {
157  vt100compat = 1;
158  } else if (!strncmp(term, "crt", 3)) {
159  /* Both crt terminals support color */
160  vt100compat = 1;
161  }
162  }
163 
164 end:
165  if (vt100compat) {
166  /* Make commands show up in nice colors */
168  snprintf(prepdata, sizeof(prepdata), "%c[%dm", ESC, COLOR_BROWN);
169  snprintf(enddata, sizeof(enddata), "%c[%dm", ESC, COLOR_BLACK);
170  snprintf(quitdata, sizeof(quitdata), "%c[0m", ESC);
171  } else if (ast_opt_force_black_background) {
172  snprintf(prepdata, sizeof(prepdata), "%c[%d;%d;%dm", ESC, ATTR_BRIGHT, COLOR_BROWN, COLOR_BLACK + 10);
173  snprintf(enddata, sizeof(enddata), "%c[%d;%d;%dm", ESC, ATTR_RESET, COLOR_WHITE, COLOR_BLACK + 10);
174  snprintf(quitdata, sizeof(quitdata), "%c[0m", ESC);
175  } else {
176  snprintf(prepdata, sizeof(prepdata), "%c[%d;%dm", ESC, ATTR_BRIGHT, COLOR_BROWN);
177  snprintf(enddata, sizeof(enddata), "%c[%d;%dm", ESC, ATTR_RESET, COLOR_WHITE);
178  snprintf(quitdata, sizeof(quitdata), "%c[0m", ESC);
179  }
180  }
181  return 0;
182 }
183 
184 char *term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
185 {
186  int attr = 0;
187 
188  if (!vt100compat) {
189  ast_copy_string(outbuf, inbuf, maxout);
190  return outbuf;
191  }
192  if (!fgcolor) {
193  ast_copy_string(outbuf, inbuf, maxout);
194  return outbuf;
195  }
196 
197  if (fgcolor & 128) {
199  fgcolor &= ~128;
200  }
201 
202  if (bgcolor) {
203  bgcolor &= ~128;
204  }
205 
207  fgcolor = opposite(fgcolor);
208  }
209 
211  snprintf(outbuf, maxout, "%c[%d;%d;%dm%s%c[%d;%dm", ESC, attr, fgcolor, bgcolor + 10, inbuf, ESC, COLOR_WHITE, COLOR_BLACK + 10);
212  } else {
213  snprintf(outbuf, maxout, "%c[%d;%dm%s%c[0m", ESC, attr, fgcolor, inbuf, ESC);
214  }
215  return outbuf;
216 }
217 
218 static void check_fgcolor(int *fgcolor, int *attr)
219 {
220  if (*fgcolor & 128) {
222  *fgcolor &= ~128;
223  }
224 
226  *fgcolor = opposite(*fgcolor);
227  }
228 }
229 
230 static void check_bgcolor(int *bgcolor)
231 {
232  if (*bgcolor) {
233  *bgcolor &= ~128;
234  }
235 }
236 
237 static int check_colors_allowed(int fgcolor)
238 {
239  return (!vt100compat || !fgcolor) ? 0 : 1;
240 }
241 
242 int ast_term_color_code(struct ast_str **str, int fgcolor, int bgcolor)
243 {
244  int attr = 0;
245 
246  if (!check_colors_allowed(fgcolor)) {
247  return -1;
248  }
249 
250  check_fgcolor(&fgcolor, &attr);
251  check_bgcolor(&bgcolor);
252 
254  ast_str_append(str, 0, "%c[%d;%d;%dm", ESC, attr, fgcolor, COLOR_BLACK + 10);
255  } else if (bgcolor) {
256  ast_str_append(str, 0, "%c[%d;%d;%dm", ESC, attr, fgcolor, bgcolor + 10);
257  } else {
258  ast_str_append(str, 0, "%c[%d;%dm", ESC, attr, fgcolor);
259  }
260 
261  return 0;
262 }
263 
264 char *term_color_code(char *outbuf, int fgcolor, int bgcolor, int maxout)
265 {
266  int attr = 0;
267 
268  if (!check_colors_allowed(fgcolor)) {
269  *outbuf = '\0';
270  return outbuf;
271  }
272 
273  check_fgcolor(&fgcolor, &attr);
274  check_bgcolor(&bgcolor);
275 
277  snprintf(outbuf, maxout, "%c[%d;%d;%dm", ESC, attr, fgcolor, COLOR_BLACK + 10);
278  } else if (bgcolor) {
279  snprintf(outbuf, maxout, "%c[%d;%d;%dm", ESC, attr, fgcolor, bgcolor + 10);
280  } else {
281  snprintf(outbuf, maxout, "%c[%d;%dm", ESC, attr, fgcolor);
282  }
283 
284  return outbuf;
285 }
286 
287 char *term_strip(char *outbuf, const char *inbuf, int maxout)
288 {
289  char *outbuf_ptr = outbuf;
290  const char *inbuf_ptr = inbuf;
291 
292  while (outbuf_ptr < outbuf + maxout) {
293  switch (*inbuf_ptr) {
294  case ESC:
295  while (*inbuf_ptr && (*inbuf_ptr != 'm'))
296  inbuf_ptr++;
297  break;
298  default:
299  *outbuf_ptr = *inbuf_ptr;
300  outbuf_ptr++;
301  }
302  if (! *inbuf_ptr)
303  break;
304  inbuf_ptr++;
305  }
306  return outbuf;
307 }
308 
309 char *term_prompt(char *outbuf, const char *inbuf, int maxout)
310 {
311  if (!vt100compat) {
312  ast_copy_string(outbuf, inbuf, maxout);
313  return outbuf;
314  }
316  snprintf(outbuf, maxout, "%c[%d;%dm%c%c[%d;%dm%s",
317  ESC, COLOR_BLUE, COLOR_BLACK + 10,
318  inbuf[0],
319  ESC, COLOR_WHITE, COLOR_BLACK + 10,
320  inbuf + 1);
321  } else if (ast_opt_light_background) {
322  snprintf(outbuf, maxout, "%c[%d;0m%c%c[%d;0m%s",
323  ESC, COLOR_BLUE,
324  inbuf[0],
325  ESC, COLOR_BLACK,
326  inbuf + 1);
327  } else {
328  snprintf(outbuf, maxout, "%c[%d;%d;0m%c%c[%d;%d;0m%s",
330  inbuf[0],
331  ESC, 0, COLOR_WHITE,
332  inbuf + 1);
333  }
334  return outbuf;
335 }
336 
337 /* filter escape sequences */
338 void term_filter_escapes(char *line)
339 {
340  int i;
341  int len = strlen(line);
342 
343  for (i = 0; i < len; i++) {
344  if (line[i] != ESC)
345  continue;
346  if ((i < (len - 2)) &&
347  (line[i + 1] == 0x5B)) {
348  switch (line[i + 2]) {
349  case 0x30:
350  case 0x31:
351  case 0x33:
352  continue;
353  }
354  }
355  /* replace ESC with a space */
356  line[i] = ' ';
357  }
358 }
359 
360 char *term_prep(void)
361 {
362  return prepdata;
363 }
364 
365 char *term_end(void)
366 {
367  return enddata;
368 }
369 
370 char *term_quit(void)
371 {
372  return quitdata;
373 }
static void check_fgcolor(int *fgcolor, int *attr)
Definition: term.c:218
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define ast_opt_force_black_background
Definition: options.h:129
static int vt100compat
Definition: term.c:44
static short convshort(char *s)
Definition: term.c:72
#define COLOR_CYAN
Definition: term.h:59
int ast_term_color_code(struct ast_str **str, int fgcolor, int bgcolor)
Append a color sequence to an ast_str.
Definition: term.c:242
#define COLOR_WHITE
Definition: term.h:61
char * term_strip(char *outbuf, const char *inbuf, int maxout)
Definition: term.c:287
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
#define COLOR_GREEN
Definition: term.h:51
const char * str
Definition: app_jack.c:144
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
static char enddata[80]
Definition: term.c:47
#define ast_opt_console
Definition: options.h:107
Utility functions.
char * term_prep(void)
Definition: term.c:360
int ast_term_init(void)
Definition: term.c:87
static char prepdata[80]
Definition: term.c:46
#define ATTR_BRIGHT
Definition: term.h:36
char * term_color_code(char *outbuf, int fgcolor, int bgcolor, int maxout)
Write a color sequence to a string.
Definition: term.c:264
#define ast_opt_no_color
Definition: options.h:112
static char quitdata[80]
Definition: term.c:48
void term_filter_escapes(char *line)
Definition: term.c:338
#define COLOR_RED
Definition: term.h:49
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Definition: term.c:184
#define COLOR_BLACK
Definition: term.h:47
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
#define ATTR_RESET
Definition: term.h:35
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_opt_light_background
Definition: options.h:128
static void check_bgcolor(int *bgcolor)
Definition: term.c:230
static const char *const termpath[]
Definition: term.c:50
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char * term_prompt(char *outbuf, const char *inbuf, int maxout)
Definition: term.c:309
int color
Definition: data.c:2664
Handy terminal functions for vt* terms.
#define COLOR_BLUE
Definition: term.h:55
#define ESC
Definition: term.h:30
#define COLOR_BROWN
Definition: term.h:53
char * term_end(void)
Definition: term.c:365
static int opposite(int color)
Definition: term.c:57
static int check_colors_allowed(int fgcolor)
Definition: term.c:237
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define COLOR_MAGENTA
Definition: term.h:57
char * term_quit(void)
Definition: term.c:370