proper header name and attribution (issue #5218)
[asterisk/asterisk.git] / term.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, 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 /*
20  *
21  * Terminal Routines 
22  * 
23  */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <sys/time.h>
29 #include <signal.h>
30 #include <errno.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include "asterisk/term.h"
41 #include "asterisk/options.h"
42 #include "asterisk/lock.h"
43 #include "asterisk/utils.h"
44
45 static int vt100compat = 0;
46
47 static char prepdata[80] = "";
48 static char enddata[80] = "";
49 static char quitdata[80] = "";
50
51 static const char *termpath[] = {
52         "/usr/share/terminfo",
53         "/usr/local/share/misc/terminfo",
54         "/usr/lib/terminfo",
55         NULL
56         };
57
58 /* Ripped off from Ross Ridge, but it's public domain code (libmytinfo) */
59 static short convshort(char *s)
60 {
61         register int a,b;
62
63         a = (int) s[0] & 0377;
64         b = (int) s[1] & 0377;
65
66         if (a == 0377 && b == 0377)
67                 return -1;
68         if (a == 0376 && b == 0377)
69                 return -2;
70
71         return a + b * 256;
72 }
73
74 int term_init(void)
75 {
76         char *term = getenv("TERM");
77         char termfile[256] = "";
78         char buffer[512] = "";
79         int termfd = -1, parseokay = 0, i;
80
81         if (!term)
82                 return 0;
83         if (!option_console || option_nocolor || !option_nofork)
84                 return 0;
85
86         for (i=0 ;; i++) {
87                 if (termpath[i] == NULL) {
88                         break;
89                 }
90                 snprintf(termfile, sizeof(termfile), "%s/%c/%s", termpath[i], *term, term);
91                 termfd = open(termfile, O_RDONLY);
92                 if (termfd > -1) {
93                         break;
94                 }
95         }
96         if (termfd > -1) {
97                 int actsize = read(termfd, buffer, sizeof(buffer) - 1);
98                 short sz_names = convshort(buffer + 2);
99                 short sz_bools = convshort(buffer + 4);
100                 short n_nums   = convshort(buffer + 6);
101
102                 /* if ((sz_names + sz_bools) & 1)
103                         sz_bools++; */
104
105                 if (sz_names + sz_bools + n_nums < actsize) {
106                         /* Offset 13 is defined in /usr/include/term.h, though we do not
107                          * include it here, as it conflicts with include/asterisk/term.h */
108                         short max_colors = convshort(buffer + 12 + sz_names + sz_bools + 13 * 2);
109                         if (max_colors > 0) {
110                                 vt100compat = 1;
111                         }
112                         parseokay = 1;
113                 }
114                 close(termfd);
115         }
116
117         if (!parseokay) {
118                 /* These comparisons should not be substrings nor case-insensitive, as
119                  * terminal types are very particular about how they treat suffixes and
120                  * capitalization.  For example, terminal type 'linux-m' does NOT
121                  * support color, while 'linux' does.  Not even all vt100* terminals
122                  * support color, either (e.g. 'vt100+fnkeys'). */
123                 if (!strcmp(term, "linux")) {
124                         vt100compat = 1;
125                 } else if (!strcmp(term, "xterm")) {
126                         vt100compat = 1;
127                 } else if (!strcmp(term, "xterm-color")) {
128                         vt100compat = 1;
129                 } else if (!strncmp(term, "Eterm", 5)) {
130                         /* Both entries which start with Eterm support color */
131                         vt100compat = 1;
132                 } else if (!strcmp(term, "vt100")) {
133                         vt100compat = 1;
134                 } else if (!strncmp(term, "crt", 3)) {
135                         /* Both crt terminals support color */
136                         vt100compat = 1;
137                 }
138         }
139
140         if (vt100compat) {
141                 /* Make commands show up in nice colors */
142                 snprintf(prepdata, sizeof(prepdata), "%c[%d;%d;%dm", ESC, ATTR_BRIGHT, COLOR_BROWN, COLOR_BLACK + 10);
143                 snprintf(enddata, sizeof(enddata), "%c[%d;%d;%dm", ESC, ATTR_RESET, COLOR_WHITE, COLOR_BLACK + 10);
144                 snprintf(quitdata, sizeof(quitdata), "%c[0m", ESC);
145         }
146         return 0;
147 }
148
149 char *term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
150 {
151         int attr=0;
152         char tmp[40];
153         if (!vt100compat) {
154                 ast_copy_string(outbuf, inbuf, maxout);
155                 return outbuf;
156         }
157         if (!fgcolor && !bgcolor) {
158                 ast_copy_string(outbuf, inbuf, maxout);
159                 return outbuf;
160         }
161         if ((fgcolor & 128) && (bgcolor & 128)) {
162                 /* Can't both be highlighted */
163                 ast_copy_string(outbuf, inbuf, maxout);
164                 return outbuf;
165         }
166         if (!bgcolor)
167                 bgcolor = COLOR_BLACK;
168
169         if (bgcolor) {
170                 bgcolor &= ~128;
171                 bgcolor += 10;
172         }
173         if (fgcolor & 128) {
174                 attr = ATTR_BRIGHT;
175                 fgcolor &= ~128;
176         }
177         if (fgcolor && bgcolor) {
178                 snprintf(tmp, sizeof(tmp), "%d;%d", fgcolor, bgcolor);
179         } else if (bgcolor) {
180                 snprintf(tmp, sizeof(tmp), "%d", bgcolor);
181         } else if (fgcolor) {
182                 snprintf(tmp, sizeof(tmp), "%d", fgcolor);
183         }
184         if (attr) {
185                 snprintf(outbuf, maxout, "%c[%d;%sm%s%c[0;%d;%dm", ESC, attr, tmp, inbuf, ESC, COLOR_WHITE, COLOR_BLACK + 10);
186         } else {
187                 snprintf(outbuf, maxout, "%c[%sm%s%c[0;%d;%dm", ESC, tmp, inbuf, ESC, COLOR_WHITE, COLOR_BLACK + 10);
188         }
189         return outbuf;
190 }
191
192 char *term_color_code(char *outbuf, int fgcolor, int bgcolor, int maxout)
193 {
194         int attr=0;
195         char tmp[40];
196         if ((!vt100compat) || (!fgcolor && !bgcolor)) {
197                 *outbuf = '\0';
198                 return outbuf;
199         }
200         if ((fgcolor & 128) && (bgcolor & 128)) {
201                 /* Can't both be highlighted */
202                 *outbuf = '\0';
203                 return outbuf;
204         }
205         if (!bgcolor)
206                 bgcolor = COLOR_BLACK;
207
208         if (bgcolor) {
209                 bgcolor &= ~128;
210                 bgcolor += 10;
211         }
212         if (fgcolor & 128) {
213                 attr = ATTR_BRIGHT;
214                 fgcolor &= ~128;
215         }
216         if (fgcolor && bgcolor) {
217                 snprintf(tmp, sizeof(tmp), "%d;%d", fgcolor, bgcolor);
218         } else if (bgcolor) {
219                 snprintf(tmp, sizeof(tmp), "%d", bgcolor);
220         } else if (fgcolor) {
221                 snprintf(tmp, sizeof(tmp), "%d", fgcolor);
222         }
223         if (attr) {
224                 snprintf(outbuf, maxout, "%c[%d;%sm", ESC, attr, tmp);
225         } else {
226                 snprintf(outbuf, maxout, "%c[%sm", ESC, tmp);
227         }
228         return outbuf;
229 }
230
231 char *term_strip(char *outbuf, char *inbuf, int maxout)
232 {
233         char *outbuf_ptr = outbuf, *inbuf_ptr = inbuf;
234
235         while (outbuf_ptr < outbuf + maxout) {
236                 switch (*inbuf_ptr) {
237                         case ESC:
238                                 while (*inbuf_ptr && (*inbuf_ptr != 'm'))
239                                         inbuf_ptr++;
240                                 break;
241                         default:
242                                 *outbuf_ptr = *inbuf_ptr;
243                                 outbuf_ptr++;
244                 }
245                 if (! *inbuf_ptr)
246                         break;
247                 inbuf_ptr++;
248         }
249         return outbuf;
250 }
251
252 char *term_prompt(char *outbuf, const char *inbuf, int maxout)
253 {
254         if (!vt100compat) {
255                 ast_copy_string(outbuf, inbuf, maxout);
256                 return outbuf;
257         }
258         snprintf(outbuf, maxout, "%c[%d;%d;%dm%c%c[%d;%d;%dm%s",
259                 ESC, ATTR_BRIGHT, COLOR_BLUE, COLOR_BLACK + 10,
260                 inbuf[0],
261                 ESC, 0, COLOR_WHITE, COLOR_BLACK + 10,
262                 inbuf + 1);
263         return outbuf;
264 }
265
266 char *term_prep(void)
267 {
268         return prepdata;
269 }
270
271 char *term_end(void)
272 {
273         return enddata;
274 }
275
276 char *term_quit(void)
277 {
278         return quitdata;
279 }