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