wok diff busybox/stuff/busybox-1.16.1-vcsa2txt.u @ rev 5711
busybox: add conspy
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Wed Jun 23 21:48:13 2010 +0200 (2010-06-23) |
parents | 2a5e098a34ac |
children | 42de4dc1d8d6 |
line diff
1.1 --- a/busybox/stuff/busybox-1.16.1-vcsa2txt.u Fri Jun 04 17:00:07 2010 +0200 1.2 +++ b/busybox/stuff/busybox-1.16.1-vcsa2txt.u Wed Jun 23 21:48:13 2010 +0200 1.3 @@ -1,6 +1,14 @@ 1.4 --- busybox-1.16.1/include/applets.h 1.5 +++ busybox-1.16.1/include/applets.h 1.6 -@@ -420,6 +420,7 @@ 1.7 +@@ -105,6 +105,7 @@ 1.8 + IF_CLEAR(APPLET(clear, _BB_DIR_USR_BIN, _BB_SUID_DROP)) 1.9 + IF_CMP(APPLET(cmp, _BB_DIR_USR_BIN, _BB_SUID_DROP)) 1.10 + IF_COMM(APPLET(comm, _BB_DIR_USR_BIN, _BB_SUID_DROP)) 1.11 ++IF_VCSA2TXT(APPLET(conspy, _BB_DIR_USR_BIN, _BB_SUID_DROP)) 1.12 + IF_CP(APPLET_NOEXEC(cp, cp, _BB_DIR_BIN, _BB_SUID_DROP, cp)) 1.13 + IF_CPIO(APPLET(cpio, _BB_DIR_BIN, _BB_SUID_DROP)) 1.14 + IF_CROND(APPLET(crond, _BB_DIR_USR_SBIN, _BB_SUID_DROP)) 1.15 +@@ -420,6 +421,7 @@ 1.16 IF_UUDECODE(APPLET(uudecode, _BB_DIR_USR_BIN, _BB_SUID_DROP)) 1.17 IF_UUENCODE(APPLET(uuencode, _BB_DIR_USR_BIN, _BB_SUID_DROP)) 1.18 IF_VCONFIG(APPLET(vconfig, _BB_DIR_SBIN, _BB_SUID_DROP)) 1.19 @@ -11,14 +19,38 @@ 1.20 1.21 --- busybox-1.16.1/include/usage.h 1.22 +++ busybox-1.16.1/include/usage.h 1.23 -@@ -5011,6 +5011,13 @@ 1.24 +@@ -440,6 +440,23 @@ 1.25 + "\n -1 Close stdout" \ 1.26 + "\n -2 Close stderr" \ 1.27 + 1.28 ++#define conspy_trivial_usage \ 1.29 ++ "[-vcsnd] [-x rows] [-y lines] [virtual_console]" 1.30 ++#define conspy_full_usage "\n\n" \ 1.31 ++ "A text-mode VNC like program for Linux virtual terminals.\n" \ 1.32 ++ "\nTo exit, quickly press escape 3 times.\n" \ 1.33 ++ "\nvirtual_console:\n" \ 1.34 ++ " omitted Track the current console.\n" \ 1.35 ++ " 1..63 Virtual console N.\n" \ 1.36 ++ "\nOptions:" \ 1.37 ++ "\n -v Don't send keystrokes to the console." \ 1.38 ++ "\n -c May create device in /dev." \ 1.39 ++ "\n -s Open a SHELL session." \ 1.40 ++ "\n -n No colors. Black & white only." \ 1.41 ++ "\n -d Dump console to stdout."\ 1.42 ++ "\n -x r Skip the r first rows."\ 1.43 ++ "\n -y l Skip the l first lines."\ 1.44 ++ 1.45 + #define setuidgid_trivial_usage \ 1.46 + "USER PROG ARGS" 1.47 + #define setuidgid_full_usage "\n\n" \ 1.48 +@@ -5011,6 +5028,13 @@ 1.49 "\n set_ingress_map [vlan-name] [skb_priority] [vlan_qos]" \ 1.50 "\n set_name_type [name-type]" \ 1.51 1.52 +#define vcsa2txt_trivial_usage \ 1.53 + "stdin" 1.54 +#define vcsa2txt_full_usage \ 1.55 -+ "Filter /dev/vcsa* to ansi escape sequences" 1.56 ++ " Filter /dev/vcsa* to ansi escape sequences" 1.57 +#define vcsa2txt_example_usage \ 1.58 + "# vcsa2txt < /dev/vcsa1\n" 1.59 + 1.60 @@ -33,7 +65,7 @@ 1.61 Write a message to all users that are logged in. 1.62 1.63 +config VCSA2TXT 1.64 -+ bool "vcsa2txt" 1.65 ++ bool "vcsa2txt/conspy" 1.66 + default n 1.67 + help 1.68 + Filter /dev/vcsa* output to ansi escape sequences. 1.69 @@ -52,83 +84,493 @@ 1.70 1.71 --- busybox-1.16.1/util-linux/vcsa2txt.c 1.72 +++ busybox-1.16.1/util-linux/vcsa2txt.c 1.73 -@@ -0,0 +1,79 @@ 1.74 +@@ -0,0 +1,489 @@ 1.75 +/* vi: set sw=4 ts=4: */ 1.76 +/* 1.77 -+ * /dev/vcsa* filter for busybox 1.78 ++ * A text-mode VNC like program for Linux virtual terminals. 1.79 + * 1.80 + * pascal.bellard@ads-lu.com 1.81 + * 1.82 ++ * Based on Russell Stuart's conspy.c 1.83 ++ * http://ace-host.stuart.id.au/russell/files/conspy.c 1.84 ++ * 1.85 + * Licensed under GPLv2 or later, see file License in this tarball for details. 1.86 ++ * 1.87 ++ * example : conspy num shared access to console num 1.88 ++ * or conspy -d num screenshot of console num 1.89 ++ * or conspy -cs num poor man's GNU screen like 1.90 + */ 1.91 -+ 1.92 ++ 1.93 ++//applet:IF_CONSPY(APPLET(conspy, _BB_DIR_BIN, _BB_SUID_DROP)) 1.94 ++ 1.95 ++//kbuild:lib-$(CONFIG_CONSPY) += conspy.o 1.96 ++ 1.97 ++//config:config CONSPY 1.98 ++//config: bool "conspy" 1.99 ++//config: default n 1.100 ++//config: help 1.101 ++//config: A text-mode VNC like program for Linux virtual terminals. 1.102 ++//config: example : conspy num shared access to console num 1.103 ++//config: or conspy -d num screenshot of console num 1.104 ++//config: or conspy -cs num poor man's GNU screen like 1.105 ++ 1.106 ++//usage:#define conspy_trivial_usage 1.107 ++//usage: "[-vcsndf] [-x ROW] [-y LINE] [CONSOLE_NO]" 1.108 ++//usage:#define conspy_full_usage "\n\n" 1.109 ++//usage: "A text-mode VNC like program for Linux virtual consoles." 1.110 ++//usage: "\nTo exit, quickly press ESC 3 times." 1.111 ++//usage: "\n" 1.112 ++//usage: "\nOptions:" 1.113 ++//usage: "\n -v Don't send keystrokes to the console" 1.114 ++//usage: "\n -c Create missing devices in /dev" 1.115 ++//usage: "\n -s Open a SHELL session" 1.116 ++//usage: "\n -n Black & white" 1.117 ++//usage: "\n -d Dump console to stdout" 1.118 ++//usage: "\n -f Follow cursor" 1.119 ++//usage: "\n -x ROW Starting row" 1.120 ++//usage: "\n -y LINE Starting line" 1.121 ++ 1.122 +#include "libbb.h" 1.123 ++#include <sys/kd.h> 1.124 ++ 1.125 ++struct screen_info { 1.126 ++ unsigned char lines, rows, cursor_x, cursor_y; 1.127 ++}; 1.128 ++ 1.129 ++#define CHAR(x) ((x)[0]) 1.130 ++#define ATTR(x) ((x)[1]) 1.131 ++#define NEXT(x) ((x)+=2) 1.132 ++#define DATA(x) (* (short *) (x)) 1.133 ++ 1.134 ++struct globals { 1.135 ++ char* data; 1.136 ++ int size; 1.137 ++ int x, y; 1.138 ++ int kbd_fd; 1.139 ++ unsigned width; 1.140 ++ unsigned height; 1.141 ++ char last_attr; 1.142 ++ int ioerror_count; 1.143 ++ int key_count; 1.144 ++ int escape_count; 1.145 ++ int nokeys; 1.146 ++ int current; 1.147 ++ int vcsa_fd; 1.148 ++ struct screen_info info; 1.149 ++ struct termios term_orig; 1.150 ++}; 1.151 ++ 1.152 ++#define G (*ptr_to_globals) 1.153 ++#define INIT_G() do { \ 1.154 ++ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 1.155 ++} while (0) 1.156 ++ 1.157 ++enum { 1.158 ++ FLAG_v, // view only 1.159 ++ FLAG_c, // create device if need 1.160 ++ FLAG_s, // session 1.161 ++ FLAG_n, // no colors 1.162 ++ FLAG_d, // dump screen 1.163 ++ FLAG_f, // follow cursor 1.164 ++}; 1.165 ++#define FLAG(x) (1 << FLAG_##x) 1.166 ++#define BW (option_mask32 & FLAG(n)) 1.167 ++ 1.168 ++static void screen_read_close(void) 1.169 ++{ 1.170 ++ unsigned i, j; 1.171 ++ char *data = G.data + G.current; 1.172 ++ 1.173 ++ xread(G.vcsa_fd, data, G.size); 1.174 ++ G.last_attr = 0; 1.175 ++ for (i = 0; i < G.info.lines; i++) { 1.176 ++ for (j = 0; j < G.info.rows; j++, NEXT(data)) { 1.177 ++ unsigned x = j - G.x; // if will catch j < G.x too 1.178 ++ unsigned y = i - G.y; // if will catch i < G.y too 1.179 ++ 1.180 ++ if (CHAR(data) < ' ') 1.181 ++ CHAR(data) = ' '; 1.182 ++ if (y >= G.height || x >= G.width) 1.183 ++ DATA(data) = 0; 1.184 ++ } 1.185 ++ } 1.186 ++ close(G.vcsa_fd); 1.187 ++} 1.188 ++ 1.189 ++static void screen_char(char *data) 1.190 ++{ 1.191 ++ if (!BW && G.last_attr != ATTR(data)) { 1.192 ++ // BLGCRMOW 1.193 ++ static const char color[8] = "04261537"; 1.194 ++ 1.195 ++ printf("\033[%c;4%c;3%cm", 1.196 ++ (ATTR(data) & 8) ? '1' // bold 1.197 ++ : '0', // defaults 1.198 ++ color[(ATTR(data) >> 4) & 7], color[ATTR(data) & 7]); 1.199 ++ G.last_attr = ATTR(data); 1.200 ++ } 1.201 ++ bb_putchar(CHAR(data)); 1.202 ++} 1.203 ++ 1.204 ++#define clrscr() printf("\033[1;1H" "\033[0J") 1.205 ++#define curoff() printf("\033[?25l") 1.206 ++ 1.207 ++static void curon(void) 1.208 ++{ 1.209 ++ printf("\033[?25h"); 1.210 ++} 1.211 ++ 1.212 ++static void gotoxy(int row, int line) 1.213 ++{ 1.214 ++ printf("\033[%u;%uH", line + 1, row + 1); 1.215 ++} 1.216 ++ 1.217 ++static void screen_dump(void) 1.218 ++{ 1.219 ++ int linefeed_cnt; 1.220 ++ int line, row; 1.221 ++ int linecnt = G.info.lines - G.y; 1.222 ++ char *data = G.data + G.current + (2 * G.y * G.info.rows); 1.223 ++ 1.224 ++ linefeed_cnt = 0; 1.225 ++ for (line = 0; line < linecnt && line < G.height; line++) { 1.226 ++ int space_cnt = 0; 1.227 ++ for (row = 0; row < G.info.rows; row++, NEXT(data)) { 1.228 ++ unsigned tty_row = row - G.x; // if will catch row < G.x too 1.229 ++ 1.230 ++ if (tty_row >= G.width) 1.231 ++ continue; 1.232 ++ space_cnt++; 1.233 ++ if (BW && (CHAR(data) | ' ') == ' ') 1.234 ++ continue; 1.235 ++ while (linefeed_cnt != 0) { 1.236 ++ bb_putchar('\r'); 1.237 ++ bb_putchar('\n'); 1.238 ++ linefeed_cnt--; 1.239 ++ } 1.240 ++ while (--space_cnt) 1.241 ++ bb_putchar(' '); 1.242 ++ screen_char(data); 1.243 ++ } 1.244 ++ linefeed_cnt++; 1.245 ++ } 1.246 ++} 1.247 ++ 1.248 ++static void curmove(void) 1.249 ++{ 1.250 ++ unsigned cx = G.info.cursor_x - G.x; 1.251 ++ unsigned cy = G.info.cursor_y - G.y; 1.252 ++ 1.253 ++ if (cx >= G.width || cy >= G.height) { 1.254 ++ curoff(); 1.255 ++ } else { 1.256 ++ curon(); 1.257 ++ gotoxy(cx, cy); 1.258 ++ } 1.259 ++ fflush_all(); 1.260 ++} 1.261 ++ 1.262 ++static void cleanup(int code) 1.263 ++{ 1.264 ++ curon(); 1.265 ++ fflush_all(); 1.266 ++ tcsetattr(G.kbd_fd, TCSANOW, &G.term_orig); 1.267 ++ if (ENABLE_FEATURE_CLEAN_UP) { 1.268 ++ free(ptr_to_globals); 1.269 ++ close(G.kbd_fd); 1.270 ++ } 1.271 ++ // Reset attributes 1.272 ++ if (!BW) 1.273 ++ printf("\033[0m"); 1.274 ++ bb_putchar('\n'); 1.275 ++ if (code > 1) 1.276 ++ kill_myself_with_sig(code); // does not return 1.277 ++ exit(code); 1.278 ++} 1.279 ++ 1.280 ++static void get_initial_data(const char* vcsa_name) 1.281 ++{ 1.282 ++ G.vcsa_fd = xopen(vcsa_name, O_RDONLY); 1.283 ++ xread(G.vcsa_fd, &G.info, 4); 1.284 ++ G.size = G.info.rows * G.info.lines * 2; 1.285 ++ G.width = G.height = UINT_MAX; 1.286 ++ G.data = xzalloc(2 * G.size); 1.287 ++ screen_read_close(); 1.288 ++} 1.289 ++ 1.290 ++static void create_cdev_if_doesnt_exist(const char* name, dev_t dev) 1.291 ++{ 1.292 ++ int fd = open(name, O_RDONLY); 1.293 ++ if (fd != -1) 1.294 ++ close(fd); 1.295 ++ else if (errno == ENOENT) 1.296 ++ mknod(name, S_IFCHR | 0660, dev); 1.297 ++} 1.298 ++ 1.299 ++static NOINLINE void start_shell_in_child(const char* tty_name) 1.300 ++{ 1.301 ++ int pid = vfork(); 1.302 ++ if (pid < 0) { 1.303 ++ bb_perror_msg_and_die("vfork"); 1.304 ++ } 1.305 ++ if (pid == 0) { 1.306 ++ struct termios termchild; 1.307 ++ char *shell = getenv("SHELL"); 1.308 ++ 1.309 ++ if (!shell) 1.310 ++ shell = (char *) DEFAULT_SHELL; 1.311 ++ signal(SIGHUP, SIG_IGN); 1.312 ++ // set tty as a controlling tty 1.313 ++ setsid(); 1.314 ++ // make tty to be input, output, error 1.315 ++ close(0); 1.316 ++ xopen(tty_name, O_RDWR); // uses fd 0 1.317 ++ xdup2(0, 1); 1.318 ++ xdup2(0, 2); 1.319 ++ ioctl(0, TIOCSCTTY, 1); 1.320 ++ tcsetpgrp(0, getpid()); 1.321 ++ tcgetattr(0, &termchild); 1.322 ++ termchild.c_lflag |= ECHO; 1.323 ++ termchild.c_oflag |= ONLCR | XTABS; 1.324 ++ termchild.c_iflag |= ICRNL; 1.325 ++ termchild.c_iflag &= ~IXOFF; 1.326 ++ tcsetattr_stdin_TCSANOW(&termchild); 1.327 ++ execl(shell, shell, "-i", (char *) NULL); 1.328 ++ bb_simple_perror_msg_and_die(shell); 1.329 ++ } 1.330 ++} 1.331 + 1.332 +int vcsa2txt_main(int argc) MAIN_EXTERNALLY_VISIBLE; 1.333 +int vcsa2txt_main(int argc) 1.334 +{ 1.335 -+ struct { 1.336 -+ unsigned char l, c, x, y; // man 4 console_codes 1.337 -+ } scrn; 1.338 -+ unsigned char last = 0, ch[2]; // BLGCRMOW 1.339 -+ static unsigned char end[5] = "\e[0m\n", color[8] = "04261537"; 1.340 -+ int sp, lf, x; 1.341 -+ 1.342 -+ if (safe_read(0, &scrn, 4) < 0) return 1; 1.343 -+ for (lf = 0; scrn.l; lf++, scrn.l--) { 1.344 -+ for (sp = x = 0; ++x <= scrn.c;) { 1.345 -+ if (safe_read(0, &ch[0], 2) < 0) return 1; 1.346 -+ if (argc > 1) ch[1] = 0; 1.347 -+ sp++; 1.348 -+ if (last == ch[1] && ch[0] == ' ') continue; 1.349 -+ for (lf++; --lf;) bb_putchar('\n'); 1.350 -+ while (--sp) bb_putchar(' '); 1.351 -+#define ENABLE_VCSA_PACKED 1 1.352 -+#if ENABLE_VCSA_PACKED 1.353 -+ if (last ^= ch[1]) { 1.354 -+ char esc[16],*s; 1.355 -+ struct offsets { 1.356 -+ char mask, type, shr; 1.357 -+ } *p; 1.358 -+ static struct offsets offset[3] = { 1.359 -+ {8,0,1}, {0x70,'4',4}, {7,'3',0} 1.360 -+ }; 1.361 -+ static char init = 0x7F; 1.362 ++ INIT_G(); 1.363 ++ option_mask32 = FLAG(n); 1.364 ++ if (argc < 2) option_mask32 = 0; 1.365 ++ xread(0, &G.info, 4); 1.366 ++ G.size = G.info.rows * G.info.lines * 2; 1.367 ++ G.width = G.height = UINT_MAX; 1.368 ++ G.data = xzalloc(G.size); 1.369 ++ screen_read_close(); 1.370 ++ screen_dump(); 1.371 ++ bb_putchar('\n'); 1.372 ++ if (ENABLE_FEATURE_CLEAN_UP) { 1.373 ++ free(ptr_to_globals); 1.374 ++ close(G.kbd_fd); 1.375 ++ } 1.376 ++ return 0; 1.377 ++} 1.378 ++ 1.379 ++int conspy_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE; 1.380 ++int conspy_main(int argc UNUSED_PARAM, char **argv) 1.381 ++{ 1.382 ++ char vcsa_name[sizeof("/dev/vcsa") + 2]; 1.383 ++ char tty_name[sizeof("/dev/tty") + 2]; 1.384 ++#define keybuf bb_common_bufsiz1 1.385 ++ struct termios termbuf; 1.386 ++ unsigned opts; 1.387 ++ unsigned ttynum; 1.388 ++ int poll_timeout_ms; 1.389 ++#if ENABLE_LONG_OPTS 1.390 ++ static const char getopt_longopts[] ALIGN1 = 1.391 ++ "viewonly\0" No_argument "v" 1.392 ++ "createdevice\0" No_argument "c" 1.393 ++ "session\0" No_argument "s" 1.394 ++ "nocolors\0" No_argument "n" 1.395 ++ "dump\0" No_argument "d" 1.396 ++ "follow\0" No_argument "f" 1.397 ++ ; 1.398 ++ 1.399 ++ applet_long_options = getopt_longopts; 1.400 ++#endif 1.401 ++ INIT_G(); 1.402 ++ 1.403 ++ opt_complementary = "x+:y+"; // numeric params 1.404 ++ opts = getopt32(argv, "vcsndfx:y:", &G.x, &G.y); 1.405 ++ argv += optind; 1.406 ++ ttynum = 0; 1.407 ++ if (argv[0]) { 1.408 ++ ttynum = xatou_range(argv[0], 0, 63); 1.409 ++ } 1.410 ++ sprintf(vcsa_name, "/dev/vcsa%u", ttynum); 1.411 ++ sprintf(tty_name, "%s%u", "/dev/tty", ttynum); 1.412 ++ if (opts & FLAG(c)) { 1.413 ++ if ((opts & (FLAG(s)|FLAG(v))) != FLAG(v)) 1.414 ++ create_cdev_if_doesnt_exist(tty_name, makedev(4, ttynum)); 1.415 ++ create_cdev_if_doesnt_exist(vcsa_name, makedev(7, 128 + ttynum)); 1.416 ++ } 1.417 ++ if ((opts & FLAG(s)) && ttynum) { 1.418 ++ start_shell_in_child(tty_name); 1.419 ++ } 1.420 ++ 1.421 ++ get_initial_data(vcsa_name); 1.422 ++ G.kbd_fd = xopen(CURRENT_TTY, O_RDONLY); 1.423 ++ if (opts & FLAG(d)) { 1.424 ++ screen_dump(); 1.425 ++ bb_putchar('\n'); 1.426 ++ if (ENABLE_FEATURE_CLEAN_UP) { 1.427 ++ free(ptr_to_globals); 1.428 ++ close(G.kbd_fd); 1.429 ++ } 1.430 ++ return 0; 1.431 ++ } 1.432 ++ 1.433 ++ bb_signals(BB_FATAL_SIGS, cleanup); 1.434 ++ // All characters must be passed through to us unaltered 1.435 ++ tcgetattr(G.kbd_fd, &G.term_orig); 1.436 ++ termbuf = G.term_orig; 1.437 ++ termbuf.c_iflag &= ~(BRKINT|INLCR|ICRNL|IXON|IXOFF|IUCLC|IXANY|IMAXBEL); 1.438 ++ termbuf.c_oflag &= ~(OPOST); 1.439 ++ termbuf.c_lflag &= ~(ISIG|ICANON|ECHO); 1.440 ++ termbuf.c_cc[VMIN] = 1; 1.441 ++ termbuf.c_cc[VTIME] = 0; 1.442 ++ tcsetattr(G.kbd_fd, TCSANOW, &termbuf); 1.443 ++ poll_timeout_ms = 250; 1.444 ++ while (1) { 1.445 ++ struct pollfd pfd; 1.446 ++ int bytes_read; 1.447 ++ int i, j; 1.448 ++ char *data, *old; 1.449 ++ 1.450 ++ old = G.data + G.current; 1.451 ++ G.current = G.size - G.current; 1.452 ++ data = G.data + G.current; 1.453 + 1.454 -+ s = esc+2; 1.455 -+ *(short *)esc = ntohs(256*'\e'+'['); 1.456 -+ p = offset; 1.457 -+ do { 1.458 -+ if ((init|last) & p->mask) { 1.459 -+ int c = (ch[1] & p->mask) >> p->shr; 1.460 -+ 1.461 -+ if ((*s = p->type) != 0) s++; 1.462 -+ else if (c == 0) { 1.463 -+ c = 2; 1.464 -+ *s++ = '2'; /* normal */ 1.465 ++ // Close & re-open vcsa in case they have 1.466 ++ // swapped virtual consoles 1.467 ++ G.vcsa_fd = xopen(vcsa_name, O_RDONLY); 1.468 ++ xread(G.vcsa_fd, &G.info, 4); 1.469 ++ if (G.size != (G.info.rows * G.info.lines * 2)) { 1.470 ++ cleanup(1); 1.471 ++ } 1.472 ++ i = G.width; 1.473 ++ j = G.height; 1.474 ++ get_terminal_width_height(G.kbd_fd, &G.width, &G.height); 1.475 ++ if ((option_mask32 & FLAG(f))) { 1.476 ++ int nx = G.info.cursor_x - G.width + 1; 1.477 ++ int ny = G.info.cursor_y - G.height + 1; 1.478 ++ 1.479 ++ if (G.info.cursor_x < G.x) { 1.480 ++ G.x = G.info.cursor_x; 1.481 ++ i = 0; // force refresh 1.482 + } 1.483 -+ *s++ = color[c]; 1.484 -+ *s++ = ';'; 1.485 -+ } 1.486 -+ } while (p++->shr); 1.487 -+ s[-1] = 'm'; 1.488 -+ init = 0; 1.489 -+ fwrite(esc,s-esc,1,stdout); 1.490 -+ } 1.491 -+ last = ch[1]; 1.492 -+#else 1.493 -+ if (last != ch[1]) { 1.494 -+ static char esc[10] = "\e[0;47;37m"; 1.495 -+ 1.496 -+ esc[2] = ((last = ch[1]) & 8) ? '1' /* bold */ : '0' /* defaults */; 1.497 -+ esc[sizeof(esc)-5] = color[(ch[1] >> 4) & 7]; 1.498 -+ esc[sizeof(esc)-2] = color[ch[1] & 7]; 1.499 -+ fwrite(esc,sizeof(esc),1,stdout); 1.500 -+ } 1.501 -+#endif 1.502 -+ bb_putchar(ch[0]); 1.503 ++ if (nx > G.x) { 1.504 ++ G.x = nx; 1.505 ++ i = 0; // force refresh 1.506 ++ } 1.507 ++ if (G.info.cursor_y < G.y) { 1.508 ++ G.y = G.info.cursor_y; 1.509 ++ i = 0; // force refresh 1.510 ++ } 1.511 ++ if (ny > G.y) { 1.512 ++ G.y = ny; 1.513 ++ i = 0; // force refresh 1.514 ++ } 1.515 ++ } 1.516 ++ 1.517 ++ // Scan console data and redraw our tty where needed 1.518 ++ screen_read_close(); 1.519 ++ if (i != G.width || j != G.height) { 1.520 ++ clrscr(); 1.521 ++ screen_dump(); 1.522 ++ } 1.523 ++ else for (i = 0; i < G.info.lines; i++) { 1.524 ++ char *last = last; 1.525 ++ char *first = NULL; 1.526 ++ int iy = i - G.y; 1.527 ++ 1.528 ++ if (iy >= (int) G.height) 1.529 ++ break; 1.530 ++ for (j = 0; j < G.info.rows; j++) { 1.531 ++ last = data; 1.532 ++ if (DATA(data) != DATA(old) && iy >= 0) { 1.533 ++ unsigned jx = j - G.x; 1.534 ++ 1.535 ++ last = NULL; 1.536 ++ if (first == NULL && jx < G.width) { 1.537 ++ first = data; 1.538 ++ gotoxy(jx, iy); 1.539 ++ } 1.540 ++ } 1.541 ++ NEXT(old); 1.542 ++ NEXT(data); 1.543 ++ } 1.544 ++ if (first == NULL) 1.545 ++ continue; 1.546 ++ if (last == NULL) 1.547 ++ last = data; 1.548 ++ 1.549 ++ // Write the data to the screen 1.550 ++ for (; first < last; NEXT(first)) 1.551 ++ screen_char(first); 1.552 ++ } 1.553 ++ curmove(); 1.554 ++ 1.555 ++ // Wait for local user keypresses 1.556 ++ pfd.fd = G.kbd_fd; 1.557 ++ pfd.events = POLLIN; 1.558 ++ bytes_read = 0; 1.559 ++ switch (poll(&pfd, 1, poll_timeout_ms)) { 1.560 ++ char *k; 1.561 ++ case -1: 1.562 ++ if (errno != EINTR) 1.563 ++ cleanup(1); 1.564 ++ break; 1.565 ++ case 0: 1.566 ++ if (++G.nokeys >= 4) 1.567 ++ G.nokeys = G.escape_count = 0; 1.568 ++ break; 1.569 ++ default: 1.570 ++ // Read the keys pressed 1.571 ++ k = keybuf + G.key_count; 1.572 ++ bytes_read = read(G.kbd_fd, k, sizeof(keybuf) - G.key_count); 1.573 ++ if (bytes_read < 0) 1.574 ++ cleanup(1); 1.575 ++ 1.576 ++ // Do exit processing 1.577 ++ for (i = 0; i < bytes_read; i++) { 1.578 ++ if (k[i] != '\033') G.escape_count = 0; 1.579 ++ else if (++G.escape_count >= 3) 1.580 ++ cleanup(0); 1.581 ++ } 1.582 ++ } 1.583 ++ poll_timeout_ms = 250; 1.584 ++ 1.585 ++ // Insert all keys pressed into the virtual console's input 1.586 ++ // buffer. Don't do this if the virtual console is in scan 1.587 ++ // code mode - giving ASCII characters to a program expecting 1.588 ++ // scan codes will confuse it. 1.589 ++ if (!(option_mask32 & FLAG(v)) && G.escape_count == 0) { 1.590 ++ int handle, result; 1.591 ++ long kbd_mode; 1.592 ++ 1.593 ++ G.key_count += bytes_read; 1.594 ++ handle = xopen(tty_name, O_WRONLY); 1.595 ++ result = ioctl(handle, KDGKBMODE, &kbd_mode); 1.596 ++ if (result == -1) 1.597 ++ /* nothing */; 1.598 ++ else if (kbd_mode != K_XLATE && kbd_mode != K_UNICODE) 1.599 ++ G.key_count = 0; // scan code mode 1.600 ++ else { 1.601 ++ for (i = 0; i < G.key_count && result != -1; i++) 1.602 ++ result = ioctl(handle, TIOCSTI, keybuf + i); 1.603 ++ G.key_count -= i; 1.604 ++ if (G.key_count) 1.605 ++ memmove(keybuf, keybuf + i, G.key_count); 1.606 ++ // If there is an application on console which reacts 1.607 ++ // to keypresses, we need to make our first sleep 1.608 ++ // shorter to quickly redraw whatever it printed there. 1.609 ++ poll_timeout_ms = 20; 1.610 ++ } 1.611 ++ // Close & re-open tty in case they have 1.612 ++ // swapped virtual consoles 1.613 ++ close(handle); 1.614 ++ 1.615 ++ // We sometimes get spurious IO errors on the TTY 1.616 ++ // as programs close and re-open it 1.617 ++ if (result != -1) 1.618 ++ G.ioerror_count = 0; 1.619 ++ else if (errno != EIO || ++G.ioerror_count > 4) 1.620 ++ cleanup(1); 1.621 ++ } 1.622 + } 1.623 -+ } 1.624 -+ fwrite(end,sizeof(end),1,stdout); 1.625 -+ return 0; 1.626 +}