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