wok-next 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 932522d70bdb
children 386214f606f5
files busybox/receipt busybox/stuff/busybox-1.16.1-modinfo.u busybox/stuff/busybox-1.16.1-modprobe.u busybox/stuff/busybox-1.16.1-stat.u busybox/stuff/busybox-1.16.1-vcsa2txt.u
line diff
     1.1 --- a/busybox/receipt	Wed Jun 23 16:11:06 2010 +0200
     1.2 +++ b/busybox/receipt	Wed Jun 23 21:48:13 2010 +0200
     1.3 @@ -36,8 +36,13 @@
     1.4  EOT
     1.5      cp ../stuff/$PACKAGE-$VERSION.config .config
     1.6      make oldconfig
     1.7 -    # "CFLAGS=-O0" is a workaround for GCC 4.5.0
     1.8 -    make -j 4 "CFLAGS=-O0" && make "CFLAGS=-O0" install
     1.9 +    if [ "$(gcc --version | awk '{ print $3; exit }')" == "4.5.0" ]; then
    1.10 +	# "CFLAGS=-O0" is a workaround for GCC 4.5.0 (sed crach)
    1.11 +	# "CFLAGS=-fno-tree-pta" may be a workaround for GCC 4.5.0 (sed garbage)
    1.12 +	make -j 4 "CFLAGS=-O0" && make "CFLAGS=-O0" install
    1.13 +    else
    1.14 +	make -j 4 && make install
    1.15 +    fi
    1.16      echo "Chmod 4755 on busybox binary..."
    1.17      chmod 4755 _install/bin/busybox
    1.18  }
    1.19 @@ -88,10 +93,10 @@
    1.20  		[ -e $ROOT$i ] || continue
    1.21  		if [ -z "$answer" ]; then
    1.22  			echo -n "Keep installed GNU utilities ? "
    1.23 -			read answer
    1.24 +			read -t 30 answer	# by default: keep
    1.25  			case "$answer" in
    1.26 -			y*|Y*|o*|O*);;
    1.27 -			*) break;;
    1.28 +			n*|N*) break;;
    1.29 +			*) ;;
    1.30  			esac
    1.31  		fi
    1.32  		mv $ROOT$i $ROOT$i-busybox-install
     2.1 --- a/busybox/stuff/busybox-1.16.1-modinfo.u	Wed Jun 23 16:11:06 2010 +0200
     2.2 +++ b/busybox/stuff/busybox-1.16.1-modinfo.u	Wed Jun 23 21:48:13 2010 +0200
     2.3 @@ -1,6 +1,6 @@
     2.4  --- busybox-1.16.1/include/applets.h
     2.5  +++ busybox-1.16.1/include/applets.h
     2.6 -@@ -272,6 +272,7 @@
     2.7 +@@ -273,6 +273,7 @@
     2.8   IF_CRYPTPW(APPLET_ODDNAME(mkpasswd, cryptpw, _BB_DIR_USR_BIN, _BB_SUID_DROP, mkpasswd))
     2.9   IF_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_DROP))
    2.10   IF_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_DROP))
    2.11 @@ -11,7 +11,7 @@
    2.12  
    2.13  --- busybox-1.16.1/include/usage.h
    2.14  +++ busybox-1.16.1/include/usage.h
    2.15 -@@ -2967,6 +2967,20 @@
    2.16 +@@ -2984,6 +2984,20 @@
    2.17          "   which are the default for alias 'tulip2' overridden by the options 'irq=2 io=0x210'\n\n" \
    2.18          "   from the command line\n"
    2.19   
     3.1 --- a/busybox/stuff/busybox-1.16.1-modprobe.u	Wed Jun 23 16:11:06 2010 +0200
     3.2 +++ b/busybox/stuff/busybox-1.16.1-modprobe.u	Wed Jun 23 21:48:13 2010 +0200
     3.3 @@ -1,6 +1,6 @@
     3.4  --- busybox-1.16.1/include/usage.h
     3.5  +++ busybox-1.16.1/include/usage.h
     3.6 -@@ -2881,7 +2881,7 @@
     3.7 +@@ -2898,7 +2898,7 @@
     3.8   #define modprobe_trivial_usage \
     3.9   	IF_MODPROBE_SMALL("[-qfwrsv] MODULE [symbol=value]...") \
    3.10   	IF_NOT_MODPROBE_SMALL("[-" \
    3.11 @@ -9,7 +9,7 @@
    3.12   		IF_FEATURE_MODPROBE_BLACKLIST("b")"] MODULE [symbol=value]...")
    3.13   #define modprobe_full_usage "\n\n" \
    3.14          "Options:" \
    3.15 -@@ -2898,6 +2898,7 @@
    3.16 +@@ -2915,6 +2915,7 @@
    3.17        "\n	-k	Make module autoclean-able" \
    3.18   	) \
    3.19        "\n	-n	Dry run" \
     4.1 --- a/busybox/stuff/busybox-1.16.1-stat.u	Wed Jun 23 16:11:06 2010 +0200
     4.2 +++ b/busybox/stuff/busybox-1.16.1-stat.u	Wed Jun 23 21:48:13 2010 +0200
     4.3 @@ -65,7 +65,7 @@
     4.4  
     4.5  --- busybox-1.16.1/include/usage.h
     4.6  +++ busybox-1.16.1/include/usage.h
     4.7 -@@ -4184,6 +4184,7 @@
     4.8 +@@ -4201,6 +4201,7 @@
     4.9        "\n	-f	Display filesystem status" \
    4.10        "\n	-L	Follow links" \
    4.11        "\n	-t	Display info in terse form" \
     5.1 --- a/busybox/stuff/busybox-1.16.1-vcsa2txt.u	Wed Jun 23 16:11:06 2010 +0200
     5.2 +++ b/busybox/stuff/busybox-1.16.1-vcsa2txt.u	Wed Jun 23 21:48:13 2010 +0200
     5.3 @@ -1,6 +1,14 @@
     5.4  --- busybox-1.16.1/include/applets.h
     5.5  +++ busybox-1.16.1/include/applets.h
     5.6 -@@ -420,6 +420,7 @@
     5.7 +@@ -105,6 +105,7 @@
     5.8 + IF_CLEAR(APPLET(clear, _BB_DIR_USR_BIN, _BB_SUID_DROP))
     5.9 + IF_CMP(APPLET(cmp, _BB_DIR_USR_BIN, _BB_SUID_DROP))
    5.10 + IF_COMM(APPLET(comm, _BB_DIR_USR_BIN, _BB_SUID_DROP))
    5.11 ++IF_VCSA2TXT(APPLET(conspy, _BB_DIR_USR_BIN, _BB_SUID_DROP))
    5.12 + IF_CP(APPLET_NOEXEC(cp, cp, _BB_DIR_BIN, _BB_SUID_DROP, cp))
    5.13 + IF_CPIO(APPLET(cpio, _BB_DIR_BIN, _BB_SUID_DROP))
    5.14 + IF_CROND(APPLET(crond, _BB_DIR_USR_SBIN, _BB_SUID_DROP))
    5.15 +@@ -420,6 +421,7 @@
    5.16   IF_UUDECODE(APPLET(uudecode, _BB_DIR_USR_BIN, _BB_SUID_DROP))
    5.17   IF_UUENCODE(APPLET(uuencode, _BB_DIR_USR_BIN, _BB_SUID_DROP))
    5.18   IF_VCONFIG(APPLET(vconfig, _BB_DIR_SBIN, _BB_SUID_DROP))
    5.19 @@ -11,14 +19,38 @@
    5.20  
    5.21  --- busybox-1.16.1/include/usage.h
    5.22  +++ busybox-1.16.1/include/usage.h
    5.23 -@@ -5011,6 +5011,13 @@
    5.24 +@@ -440,6 +440,23 @@
    5.25 +      "\n	-1		Close stdout" \
    5.26 +      "\n	-2		Close stderr" \
    5.27 + 
    5.28 ++#define conspy_trivial_usage \
    5.29 ++	"[-vcsnd] [-x rows] [-y lines] [virtual_console]"
    5.30 ++#define conspy_full_usage "\n\n" \
    5.31 ++	"A text-mode VNC like program for Linux virtual terminals.\n" \
    5.32 ++	"\nTo exit, quickly press escape 3 times.\n" \
    5.33 ++	"\nvirtual_console:\n" \
    5.34 ++	"  omitted  Track the current console.\n" \
    5.35 ++	"  1..63    Virtual console N.\n" \
    5.36 ++	"\nOptions:" \
    5.37 ++	"\n	-v	Don't send keystrokes to the console." \
    5.38 ++	"\n	-c	May create device in /dev." \
    5.39 ++	"\n	-s	Open a SHELL session." \
    5.40 ++	"\n	-n	No colors. Black & white only." \
    5.41 ++	"\n	-d	Dump console to stdout."\
    5.42 ++	"\n	-x r	Skip the r first rows."\
    5.43 ++	"\n	-y l	Skip the l first lines."\
    5.44 ++
    5.45 + #define setuidgid_trivial_usage \
    5.46 +        "USER PROG ARGS"
    5.47 + #define setuidgid_full_usage "\n\n" \
    5.48 +@@ -5011,6 +5028,13 @@
    5.49        "\n	set_ingress_map	[vlan-name] [skb_priority] [vlan_qos]" \
    5.50        "\n	set_name_type	[name-type]" \
    5.51   
    5.52  +#define vcsa2txt_trivial_usage \
    5.53  +       "stdin"
    5.54  +#define vcsa2txt_full_usage \
    5.55 -+       "Filter /dev/vcsa* to ansi escape sequences"
    5.56 ++       "	Filter /dev/vcsa* to ansi escape sequences"
    5.57  +#define vcsa2txt_example_usage \
    5.58  +       "# vcsa2txt < /dev/vcsa1\n"
    5.59  +
    5.60 @@ -33,7 +65,7 @@
    5.61   	  Write a message to all users that are logged in.
    5.62   
    5.63  +config VCSA2TXT
    5.64 -+	bool "vcsa2txt"
    5.65 ++	bool "vcsa2txt/conspy"
    5.66  +	default n
    5.67  +	help
    5.68  +	  Filter /dev/vcsa* output to ansi escape sequences.
    5.69 @@ -52,83 +84,493 @@
    5.70  
    5.71  --- busybox-1.16.1/util-linux/vcsa2txt.c
    5.72  +++ busybox-1.16.1/util-linux/vcsa2txt.c
    5.73 -@@ -0,0 +1,79 @@
    5.74 +@@ -0,0 +1,489 @@
    5.75  +/* vi: set sw=4 ts=4: */
    5.76  +/*
    5.77 -+ * /dev/vcsa* filter for busybox
    5.78 ++ * A text-mode VNC like program for Linux virtual terminals.
    5.79  + *
    5.80  + * pascal.bellard@ads-lu.com
    5.81  + *
    5.82 ++ * Based on Russell Stuart's conspy.c
    5.83 ++ *   http://ace-host.stuart.id.au/russell/files/conspy.c
    5.84 ++ *
    5.85  + * Licensed under GPLv2 or later, see file License in this tarball for details.
    5.86 ++ *
    5.87 ++ * example :	conspy num		shared access to console num
    5.88 ++ * or		conspy -d num		screenshot of console num
    5.89 ++ * or		conspy -cs num		poor man's GNU screen like
    5.90  + */
    5.91 -+ 
    5.92 ++
    5.93 ++//applet:IF_CONSPY(APPLET(conspy, _BB_DIR_BIN, _BB_SUID_DROP))
    5.94 ++
    5.95 ++//kbuild:lib-$(CONFIG_CONSPY) += conspy.o
    5.96 ++
    5.97 ++//config:config CONSPY
    5.98 ++//config:	bool "conspy"
    5.99 ++//config:	default n
   5.100 ++//config:	help
   5.101 ++//config:	  A text-mode VNC like program for Linux virtual terminals.
   5.102 ++//config:	  example : conspy num      shared access to console num
   5.103 ++//config:	  or        conspy -d num   screenshot of console num
   5.104 ++//config:	  or        conspy -cs num  poor man's GNU screen like
   5.105 ++
   5.106 ++//usage:#define conspy_trivial_usage
   5.107 ++//usage:     "[-vcsndf] [-x ROW] [-y LINE] [CONSOLE_NO]"
   5.108 ++//usage:#define conspy_full_usage "\n\n"
   5.109 ++//usage:     "A text-mode VNC like program for Linux virtual consoles."
   5.110 ++//usage:     "\nTo exit, quickly press ESC 3 times."
   5.111 ++//usage:     "\n"
   5.112 ++//usage:     "\nOptions:"
   5.113 ++//usage:     "\n	-v	Don't send keystrokes to the console"
   5.114 ++//usage:     "\n	-c	Create missing devices in /dev"
   5.115 ++//usage:     "\n	-s	Open a SHELL session"
   5.116 ++//usage:     "\n	-n	Black & white"
   5.117 ++//usage:     "\n	-d	Dump console to stdout"
   5.118 ++//usage:     "\n	-f	Follow cursor"
   5.119 ++//usage:     "\n	-x ROW	Starting row"
   5.120 ++//usage:     "\n	-y LINE	Starting line"
   5.121 ++
   5.122  +#include "libbb.h"
   5.123 ++#include <sys/kd.h>
   5.124 ++
   5.125 ++struct screen_info {
   5.126 ++	unsigned char lines, rows, cursor_x, cursor_y;
   5.127 ++};
   5.128 ++
   5.129 ++#define CHAR(x) ((x)[0])
   5.130 ++#define ATTR(x) ((x)[1])
   5.131 ++#define NEXT(x) ((x)+=2)
   5.132 ++#define DATA(x) (* (short *) (x))
   5.133 ++
   5.134 ++struct globals {
   5.135 ++	char* data;
   5.136 ++	int size;
   5.137 ++	int x, y;
   5.138 ++	int kbd_fd;
   5.139 ++	unsigned width;
   5.140 ++	unsigned height;
   5.141 ++	char last_attr;
   5.142 ++	int ioerror_count;
   5.143 ++	int key_count;
   5.144 ++	int escape_count;
   5.145 ++	int nokeys;
   5.146 ++	int current;
   5.147 ++	int vcsa_fd;
   5.148 ++	struct screen_info info;
   5.149 ++	struct termios term_orig;
   5.150 ++};
   5.151 ++
   5.152 ++#define G (*ptr_to_globals)
   5.153 ++#define INIT_G() do { \
   5.154 ++	SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
   5.155 ++} while (0)
   5.156 ++
   5.157 ++enum {
   5.158 ++	FLAG_v,  // view only
   5.159 ++	FLAG_c,  // create device if need
   5.160 ++	FLAG_s,  // session
   5.161 ++	FLAG_n,  // no colors
   5.162 ++	FLAG_d,  // dump screen
   5.163 ++	FLAG_f,  // follow cursor
   5.164 ++};
   5.165 ++#define FLAG(x) (1 << FLAG_##x)
   5.166 ++#define BW (option_mask32 & FLAG(n))
   5.167 ++
   5.168 ++static void screen_read_close(void)
   5.169 ++{
   5.170 ++	unsigned i, j;
   5.171 ++	char *data = G.data + G.current;
   5.172 ++
   5.173 ++	xread(G.vcsa_fd, data, G.size);
   5.174 ++	G.last_attr = 0;
   5.175 ++	for (i = 0; i < G.info.lines; i++) {
   5.176 ++		for (j = 0; j < G.info.rows; j++, NEXT(data)) {
   5.177 ++			unsigned x = j - G.x; // if will catch j < G.x too
   5.178 ++			unsigned y = i - G.y; // if will catch i < G.y too
   5.179 ++
   5.180 ++			if (CHAR(data) < ' ')
   5.181 ++				CHAR(data) = ' ';
   5.182 ++			if (y >= G.height || x >= G.width)
   5.183 ++				DATA(data) = 0;
   5.184 ++		}
   5.185 ++	}
   5.186 ++	close(G.vcsa_fd);
   5.187 ++}
   5.188 ++
   5.189 ++static void screen_char(char *data)
   5.190 ++{
   5.191 ++	if (!BW && G.last_attr != ATTR(data)) {
   5.192 ++		//                            BLGCRMOW
   5.193 ++		static const char color[8] = "04261537";
   5.194 ++
   5.195 ++		printf("\033[%c;4%c;3%cm",
   5.196 ++			(ATTR(data) & 8) ? '1'  // bold
   5.197 ++					 : '0', // defaults
   5.198 ++			color[(ATTR(data) >> 4) & 7], color[ATTR(data) & 7]);
   5.199 ++		G.last_attr = ATTR(data);
   5.200 ++	}
   5.201 ++	bb_putchar(CHAR(data));
   5.202 ++}
   5.203 ++
   5.204 ++#define clrscr()  printf("\033[1;1H" "\033[0J")
   5.205 ++#define curoff()  printf("\033[?25l")
   5.206 ++
   5.207 ++static void curon(void)
   5.208 ++{
   5.209 ++	printf("\033[?25h");
   5.210 ++}
   5.211 ++
   5.212 ++static void gotoxy(int row, int line)
   5.213 ++{
   5.214 ++	printf("\033[%u;%uH", line + 1, row + 1);
   5.215 ++}
   5.216 ++
   5.217 ++static void screen_dump(void)
   5.218 ++{
   5.219 ++	int linefeed_cnt;
   5.220 ++	int line, row;
   5.221 ++	int linecnt = G.info.lines - G.y;
   5.222 ++	char *data = G.data + G.current + (2 * G.y * G.info.rows);
   5.223 ++
   5.224 ++	linefeed_cnt = 0;
   5.225 ++	for (line = 0; line < linecnt && line < G.height; line++) {
   5.226 ++		int space_cnt = 0;
   5.227 ++		for (row = 0; row < G.info.rows; row++, NEXT(data)) {
   5.228 ++			unsigned tty_row = row - G.x; // if will catch row < G.x too
   5.229 ++
   5.230 ++			if (tty_row >= G.width)
   5.231 ++				continue;
   5.232 ++			space_cnt++;
   5.233 ++			if (BW && (CHAR(data) | ' ') == ' ')
   5.234 ++				continue;
   5.235 ++			while (linefeed_cnt != 0) {
   5.236 ++				bb_putchar('\r');
   5.237 ++				bb_putchar('\n');
   5.238 ++				linefeed_cnt--;
   5.239 ++			}
   5.240 ++			while (--space_cnt)
   5.241 ++				bb_putchar(' ');
   5.242 ++			screen_char(data);
   5.243 ++		}
   5.244 ++		linefeed_cnt++;
   5.245 ++	}
   5.246 ++}
   5.247 ++
   5.248 ++static void curmove(void)
   5.249 ++{
   5.250 ++	unsigned cx = G.info.cursor_x - G.x;
   5.251 ++	unsigned cy = G.info.cursor_y - G.y;
   5.252 ++
   5.253 ++	if (cx >= G.width || cy >= G.height) {
   5.254 ++		curoff();
   5.255 ++	} else {
   5.256 ++		curon();
   5.257 ++		gotoxy(cx, cy);
   5.258 ++	}
   5.259 ++	fflush_all();
   5.260 ++}
   5.261 ++
   5.262 ++static void cleanup(int code)
   5.263 ++{
   5.264 ++	curon();
   5.265 ++	fflush_all();
   5.266 ++	tcsetattr(G.kbd_fd, TCSANOW, &G.term_orig);
   5.267 ++	if (ENABLE_FEATURE_CLEAN_UP) {
   5.268 ++		free(ptr_to_globals);
   5.269 ++		close(G.kbd_fd);
   5.270 ++	}
   5.271 ++	// Reset attributes
   5.272 ++	if (!BW)
   5.273 ++		printf("\033[0m");
   5.274 ++	bb_putchar('\n');
   5.275 ++	if (code > 1)
   5.276 ++		kill_myself_with_sig(code); // does not return
   5.277 ++	exit(code);
   5.278 ++}
   5.279 ++
   5.280 ++static void get_initial_data(const char* vcsa_name)
   5.281 ++{
   5.282 ++	G.vcsa_fd = xopen(vcsa_name, O_RDONLY);
   5.283 ++	xread(G.vcsa_fd, &G.info, 4);
   5.284 ++	G.size = G.info.rows * G.info.lines * 2;
   5.285 ++	G.width = G.height = UINT_MAX;
   5.286 ++	G.data = xzalloc(2 * G.size);
   5.287 ++	screen_read_close();
   5.288 ++}
   5.289 ++
   5.290 ++static void create_cdev_if_doesnt_exist(const char* name, dev_t dev)
   5.291 ++{
   5.292 ++	int fd = open(name, O_RDONLY);
   5.293 ++	if (fd != -1)
   5.294 ++		close(fd);
   5.295 ++	else if (errno == ENOENT)
   5.296 ++		mknod(name, S_IFCHR | 0660, dev);
   5.297 ++}
   5.298 ++
   5.299 ++static NOINLINE void start_shell_in_child(const char* tty_name)
   5.300 ++{
   5.301 ++	int pid = vfork();
   5.302 ++	if (pid < 0) {
   5.303 ++		bb_perror_msg_and_die("vfork");
   5.304 ++	}
   5.305 ++	if (pid == 0) {
   5.306 ++		struct termios termchild;
   5.307 ++		char *shell = getenv("SHELL");
   5.308 ++
   5.309 ++		if (!shell)
   5.310 ++			shell = (char *) DEFAULT_SHELL;
   5.311 ++		signal(SIGHUP, SIG_IGN);
   5.312 ++		// set tty as a controlling tty
   5.313 ++		setsid();
   5.314 ++		// make tty to be input, output, error
   5.315 ++		close(0);
   5.316 ++		xopen(tty_name, O_RDWR); // uses fd 0
   5.317 ++		xdup2(0, 1);
   5.318 ++		xdup2(0, 2);
   5.319 ++		ioctl(0, TIOCSCTTY, 1);
   5.320 ++		tcsetpgrp(0, getpid());
   5.321 ++		tcgetattr(0, &termchild);
   5.322 ++		termchild.c_lflag |= ECHO;
   5.323 ++		termchild.c_oflag |= ONLCR | XTABS;
   5.324 ++		termchild.c_iflag |= ICRNL;
   5.325 ++		termchild.c_iflag &= ~IXOFF;
   5.326 ++		tcsetattr_stdin_TCSANOW(&termchild);
   5.327 ++		execl(shell, shell, "-i", (char *) NULL);
   5.328 ++		bb_simple_perror_msg_and_die(shell);
   5.329 ++	}
   5.330 ++}
   5.331  +
   5.332  +int vcsa2txt_main(int argc) MAIN_EXTERNALLY_VISIBLE;
   5.333  +int vcsa2txt_main(int argc)
   5.334  +{
   5.335 -+    struct {
   5.336 -+	unsigned char l, c, x, y; // man 4 console_codes
   5.337 -+    } scrn;
   5.338 -+    unsigned char last = 0, ch[2];                     // BLGCRMOW
   5.339 -+    static  unsigned char end[5] = "\e[0m\n", color[8] = "04261537";
   5.340 -+    int sp, lf, x;
   5.341 -+    
   5.342 -+    if (safe_read(0, &scrn, 4) < 0) return 1;
   5.343 -+    for (lf = 0; scrn.l; lf++, scrn.l--) {
   5.344 -+	for (sp = x = 0; ++x <= scrn.c;) {
   5.345 -+	    if (safe_read(0, &ch[0], 2) < 0) return 1;
   5.346 -+	    if (argc > 1) ch[1] = 0;
   5.347 -+	    sp++;
   5.348 -+	    if (last == ch[1] && ch[0] == ' ') continue;
   5.349 -+	    for (lf++; --lf;) bb_putchar('\n');
   5.350 -+	    while (--sp) bb_putchar(' ');
   5.351 -+#define ENABLE_VCSA_PACKED 1
   5.352 -+#if ENABLE_VCSA_PACKED
   5.353 -+	    if (last ^= ch[1]) {
   5.354 -+		char esc[16],*s;
   5.355 -+		struct offsets {
   5.356 -+		    char mask, type, shr;
   5.357 -+		} *p;
   5.358 -+		static struct offsets offset[3] = {
   5.359 -+		    {8,0,1}, {0x70,'4',4}, {7,'3',0}
   5.360 -+		};
   5.361 -+		static char init = 0x7F;
   5.362 ++	INIT_G();
   5.363 ++	option_mask32 = FLAG(n);
   5.364 ++	if (argc < 2) option_mask32 = 0;
   5.365 ++	xread(0, &G.info, 4);
   5.366 ++	G.size = G.info.rows * G.info.lines * 2;
   5.367 ++	G.width = G.height = UINT_MAX;
   5.368 ++	G.data = xzalloc(G.size);
   5.369 ++	screen_read_close();
   5.370 ++	screen_dump();
   5.371 ++	bb_putchar('\n');
   5.372 ++	if (ENABLE_FEATURE_CLEAN_UP) {
   5.373 ++		free(ptr_to_globals);
   5.374 ++		close(G.kbd_fd);
   5.375 ++	}
   5.376 ++	return 0;
   5.377 ++}
   5.378 ++
   5.379 ++int conspy_main(int argc UNUSED_PARAM, char **argv) MAIN_EXTERNALLY_VISIBLE;
   5.380 ++int conspy_main(int argc UNUSED_PARAM, char **argv)
   5.381 ++{
   5.382 ++	char vcsa_name[sizeof("/dev/vcsa") + 2];
   5.383 ++	char tty_name[sizeof("/dev/tty") + 2];
   5.384 ++#define keybuf bb_common_bufsiz1
   5.385 ++	struct termios termbuf;
   5.386 ++	unsigned opts;
   5.387 ++	unsigned ttynum;
   5.388 ++	int poll_timeout_ms;
   5.389 ++#if ENABLE_LONG_OPTS
   5.390 ++	static const char getopt_longopts[] ALIGN1 =
   5.391 ++		"viewonly\0"     No_argument "v"
   5.392 ++		"createdevice\0" No_argument "c"
   5.393 ++		"session\0"      No_argument "s"
   5.394 ++		"nocolors\0"     No_argument "n"
   5.395 ++		"dump\0"         No_argument "d"
   5.396 ++		"follow\0"       No_argument "f"
   5.397 ++		;
   5.398 ++
   5.399 ++	applet_long_options = getopt_longopts;
   5.400 ++#endif
   5.401 ++	INIT_G();
   5.402 ++
   5.403 ++	opt_complementary = "x+:y+"; // numeric params
   5.404 ++	opts = getopt32(argv, "vcsndfx:y:", &G.x, &G.y);
   5.405 ++	argv += optind;
   5.406 ++	ttynum = 0;
   5.407 ++	if (argv[0]) {
   5.408 ++		ttynum = xatou_range(argv[0], 0, 63);
   5.409 ++	}
   5.410 ++	sprintf(vcsa_name, "/dev/vcsa%u", ttynum);
   5.411 ++	sprintf(tty_name, "%s%u", "/dev/tty", ttynum);
   5.412 ++	if (opts & FLAG(c)) {
   5.413 ++		if ((opts & (FLAG(s)|FLAG(v))) != FLAG(v))
   5.414 ++			create_cdev_if_doesnt_exist(tty_name, makedev(4, ttynum));
   5.415 ++		create_cdev_if_doesnt_exist(vcsa_name, makedev(7, 128 + ttynum));
   5.416 ++	}
   5.417 ++	if ((opts & FLAG(s)) && ttynum) {
   5.418 ++		start_shell_in_child(tty_name);
   5.419 ++	}
   5.420 ++
   5.421 ++	get_initial_data(vcsa_name);
   5.422 ++	G.kbd_fd = xopen(CURRENT_TTY, O_RDONLY);
   5.423 ++	if (opts & FLAG(d)) {
   5.424 ++		screen_dump();
   5.425 ++		bb_putchar('\n');
   5.426 ++		if (ENABLE_FEATURE_CLEAN_UP) {
   5.427 ++			free(ptr_to_globals);
   5.428 ++			close(G.kbd_fd);
   5.429 ++		}
   5.430 ++		return 0;
   5.431 ++	}
   5.432 ++
   5.433 ++	bb_signals(BB_FATAL_SIGS, cleanup);
   5.434 ++	// All characters must be passed through to us unaltered
   5.435 ++	tcgetattr(G.kbd_fd, &G.term_orig);
   5.436 ++	termbuf = G.term_orig;
   5.437 ++	termbuf.c_iflag &= ~(BRKINT|INLCR|ICRNL|IXON|IXOFF|IUCLC|IXANY|IMAXBEL);
   5.438 ++	termbuf.c_oflag &= ~(OPOST);
   5.439 ++	termbuf.c_lflag &= ~(ISIG|ICANON|ECHO);
   5.440 ++	termbuf.c_cc[VMIN] = 1;
   5.441 ++	termbuf.c_cc[VTIME] = 0;
   5.442 ++	tcsetattr(G.kbd_fd, TCSANOW, &termbuf);
   5.443 ++	poll_timeout_ms = 250;
   5.444 ++	while (1) {
   5.445 ++		struct pollfd pfd;
   5.446 ++		int bytes_read;
   5.447 ++		int i, j;
   5.448 ++		char *data, *old;
   5.449 ++
   5.450 ++		old = G.data + G.current;
   5.451 ++		G.current = G.size - G.current;
   5.452 ++		data = G.data + G.current;
   5.453  +		
   5.454 -+		s = esc+2;
   5.455 -+		*(short *)esc = ntohs(256*'\e'+'[');
   5.456 -+		p = offset;
   5.457 -+		do {
   5.458 -+		    if ((init|last) & p->mask) {
   5.459 -+			int c = (ch[1] & p->mask) >> p->shr;
   5.460 -+		    
   5.461 -+			if ((*s = p->type) != 0) s++;
   5.462 -+			else if (c == 0) {
   5.463 -+			    c = 2;
   5.464 -+			    *s++ = '2'; /* normal */
   5.465 ++		// Close & re-open vcsa in case they have
   5.466 ++		// swapped virtual consoles
   5.467 ++		G.vcsa_fd = xopen(vcsa_name, O_RDONLY);
   5.468 ++		xread(G.vcsa_fd, &G.info, 4);
   5.469 ++		if (G.size != (G.info.rows * G.info.lines * 2)) {
   5.470 ++			cleanup(1);
   5.471 ++		}
   5.472 ++		i = G.width;
   5.473 ++		j = G.height;
   5.474 ++		get_terminal_width_height(G.kbd_fd, &G.width, &G.height);
   5.475 ++		if ((option_mask32 & FLAG(f))) {
   5.476 ++			int nx = G.info.cursor_x - G.width + 1;
   5.477 ++			int ny = G.info.cursor_y - G.height + 1;
   5.478 ++
   5.479 ++			if (G.info.cursor_x < G.x) {
   5.480 ++				G.x = G.info.cursor_x;
   5.481 ++				i = 0;	// force refresh
   5.482  +			}
   5.483 -+			*s++ = color[c];
   5.484 -+			*s++ = ';'; 
   5.485 -+		    }
   5.486 -+		} while (p++->shr);
   5.487 -+		s[-1] = 'm';
   5.488 -+		init = 0;
   5.489 -+		fwrite(esc,s-esc,1,stdout);
   5.490 -+	    }
   5.491 -+	    last = ch[1];
   5.492 -+#else
   5.493 -+	    if (last != ch[1]) {
   5.494 -+		static char esc[10] = "\e[0;47;37m";
   5.495 -+		
   5.496 -+		esc[2] = ((last = ch[1]) & 8) ? '1' /* bold */ : '0' /* defaults */;
   5.497 -+		esc[sizeof(esc)-5] = color[(ch[1] >> 4) & 7];
   5.498 -+		esc[sizeof(esc)-2] = color[ch[1] & 7];
   5.499 -+		fwrite(esc,sizeof(esc),1,stdout);
   5.500 -+	    }
   5.501 -+#endif
   5.502 -+	    bb_putchar(ch[0]);
   5.503 ++			if (nx > G.x) {
   5.504 ++				G.x = nx;
   5.505 ++				i = 0;	// force refresh
   5.506 ++			}
   5.507 ++			if (G.info.cursor_y < G.y) {
   5.508 ++				G.y = G.info.cursor_y;
   5.509 ++				i = 0;	// force refresh
   5.510 ++			}
   5.511 ++			if (ny > G.y) {
   5.512 ++				G.y = ny;
   5.513 ++				i = 0;	// force refresh
   5.514 ++			}
   5.515 ++		}
   5.516 ++
   5.517 ++		// Scan console data and redraw our tty where needed
   5.518 ++		screen_read_close();
   5.519 ++		if (i != G.width || j != G.height) {
   5.520 ++			clrscr();
   5.521 ++			screen_dump();
   5.522 ++		}
   5.523 ++		else for (i = 0; i < G.info.lines; i++) {
   5.524 ++			char *last = last;
   5.525 ++			char *first = NULL;
   5.526 ++			int iy = i - G.y;
   5.527 ++
   5.528 ++			if (iy >= (int) G.height)
   5.529 ++				break;
   5.530 ++			for (j = 0; j < G.info.rows; j++) {
   5.531 ++				last = data;
   5.532 ++				if (DATA(data) != DATA(old) && iy >= 0) {
   5.533 ++					unsigned jx = j - G.x;
   5.534 ++
   5.535 ++					last = NULL;
   5.536 ++					if (first == NULL && jx < G.width) {
   5.537 ++						first = data;
   5.538 ++						gotoxy(jx, iy);
   5.539 ++					}
   5.540 ++				}
   5.541 ++				NEXT(old);
   5.542 ++				NEXT(data);
   5.543 ++			}
   5.544 ++			if (first == NULL)
   5.545 ++				continue;
   5.546 ++			if (last == NULL)
   5.547 ++				last = data;
   5.548 ++
   5.549 ++			// Write the data to the screen
   5.550 ++			for (; first < last; NEXT(first))
   5.551 ++				screen_char(first);
   5.552 ++		}
   5.553 ++		curmove();
   5.554 ++
   5.555 ++		// Wait for local user keypresses
   5.556 ++		pfd.fd = G.kbd_fd;
   5.557 ++		pfd.events = POLLIN;
   5.558 ++		bytes_read = 0;
   5.559 ++		switch (poll(&pfd, 1, poll_timeout_ms)) {
   5.560 ++			char *k;
   5.561 ++		case -1:
   5.562 ++			if (errno != EINTR)
   5.563 ++				cleanup(1);
   5.564 ++			break;
   5.565 ++		case 0:
   5.566 ++			if (++G.nokeys >= 4)
   5.567 ++				G.nokeys = G.escape_count = 0;
   5.568 ++			break;
   5.569 ++		default:
   5.570 ++			// Read the keys pressed
   5.571 ++			k = keybuf + G.key_count;
   5.572 ++			bytes_read = read(G.kbd_fd, k, sizeof(keybuf) - G.key_count);
   5.573 ++			if (bytes_read < 0)
   5.574 ++				cleanup(1);
   5.575 ++
   5.576 ++			// Do exit processing
   5.577 ++			for (i = 0; i < bytes_read; i++) {
   5.578 ++				if (k[i] != '\033') G.escape_count = 0;
   5.579 ++				else if (++G.escape_count >= 3)
   5.580 ++					cleanup(0);
   5.581 ++			}
   5.582 ++		}
   5.583 ++		poll_timeout_ms = 250;
   5.584 ++
   5.585 ++		// Insert all keys pressed into the virtual console's input
   5.586 ++		// buffer.  Don't do this if the virtual console is in scan
   5.587 ++		// code mode - giving ASCII characters to a program expecting
   5.588 ++		// scan codes will confuse it.
   5.589 ++		if (!(option_mask32 & FLAG(v)) && G.escape_count == 0) {
   5.590 ++			int handle, result;
   5.591 ++			long kbd_mode;
   5.592 ++
   5.593 ++			G.key_count += bytes_read;
   5.594 ++			handle = xopen(tty_name, O_WRONLY);
   5.595 ++			result = ioctl(handle, KDGKBMODE, &kbd_mode);
   5.596 ++			if (result == -1)
   5.597 ++				/* nothing */;
   5.598 ++			else if (kbd_mode != K_XLATE && kbd_mode != K_UNICODE)
   5.599 ++				G.key_count = 0; // scan code mode
   5.600 ++			else {
   5.601 ++				for (i = 0; i < G.key_count && result != -1; i++)
   5.602 ++					result = ioctl(handle, TIOCSTI, keybuf + i);
   5.603 ++				G.key_count -= i;
   5.604 ++				if (G.key_count)
   5.605 ++					memmove(keybuf, keybuf + i, G.key_count);
   5.606 ++				// If there is an application on console which reacts
   5.607 ++				// to keypresses, we need to make our first sleep
   5.608 ++				// shorter to quickly redraw whatever it printed there.
   5.609 ++				poll_timeout_ms = 20;
   5.610 ++			}
   5.611 ++			// Close & re-open tty in case they have
   5.612 ++			// swapped virtual consoles
   5.613 ++			close(handle);
   5.614 ++
   5.615 ++			// We sometimes get spurious IO errors on the TTY
   5.616 ++			// as programs close and re-open it
   5.617 ++			if (result != -1)
   5.618 ++				G.ioerror_count = 0;
   5.619 ++			else if (errno != EIO || ++G.ioerror_count > 4)
   5.620 ++				cleanup(1);
   5.621 ++		}
   5.622  +	}
   5.623 -+    }
   5.624 -+    fwrite(end,sizeof(end),1,stdout);
   5.625 -+    return 0;
   5.626  +}