[master] 086a141 Add a very rudimentary 'ansi' terminal emulation.
Poul-Henning Kamp
phk at FreeBSD.org
Fri Jan 12 09:24:08 UTC 2018
commit 086a141b77ce6bb9e064f456f66c15828ca8e838
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Fri Jan 12 09:23:19 2018 +0000
Add a very rudimentary 'ansi' terminal emulation.
diff --git a/bin/varnishtest/tests/u00000.vtc b/bin/varnishtest/tests/u00000.vtc
index b6b4df3..ded88ab 100644
--- a/bin/varnishtest/tests/u00000.vtc
+++ b/bin/varnishtest/tests/u00000.vtc
@@ -30,4 +30,4 @@ delay 0.5
process p4 -kill TERM
process p4 -wait
-process p5 -log "stty -a ; sleep 1" -run
+process p5 "stty -a ; sleep 1" -run -screen_dump
diff --git a/bin/varnishtest/tests/u00009.vtc b/bin/varnishtest/tests/u00009.vtc
index e3da901..1e540bd 100644
--- a/bin/varnishtest/tests/u00009.vtc
+++ b/bin/varnishtest/tests/u00009.vtc
@@ -18,8 +18,8 @@ client c1 {
rxresp
} -run
-delay 3
+delay 10
process p1 -write {q}
-process p1 -wait
+process p1 -wait -screen_dump
diff --git a/bin/varnishtest/tests/u00010.vtc b/bin/varnishtest/tests/u00010.vtc
index 6a5c0c5..fbca6d5 100644
--- a/bin/varnishtest/tests/u00010.vtc
+++ b/bin/varnishtest/tests/u00010.vtc
@@ -18,8 +18,8 @@ client c1 {
rxresp
} -run
-delay 3
+delay 10
process p1 -write {q}
-process p1 -wait
+process p1 -wait -screen_dump
diff --git a/bin/varnishtest/tests/u00011.vtc b/bin/varnishtest/tests/u00011.vtc
index 3f0f6dd..4c29d24 100644
--- a/bin/varnishtest/tests/u00011.vtc
+++ b/bin/varnishtest/tests/u00011.vtc
@@ -22,8 +22,8 @@ delay 2
process p1 -writeln {panic.show}
-delay 2
-
process p1 -writeln {quit}
-process p1 -wait
+delay 10
+
+process p1 -wait -screen_dump
diff --git a/bin/varnishtest/vtc.c b/bin/varnishtest/vtc.c
index f507d19..6a2a476 100644
--- a/bin/varnishtest/vtc.c
+++ b/bin/varnishtest/vtc.c
@@ -725,17 +725,16 @@ static int
test_term(struct vtclog *vl)
{
FILE *p;
- int a, b, c;
+ int a, b;
- p = popen("tput -T adm3a clear 2>&1", "r");
+ p = popen("tput -T ansi clear 2>&1", "r");
if (p == NULL)
return (0);
a = fgetc(p);
b = fgetc(p);
- c = pclose(p);
- if (a == 0x1a && b == EOF && c == 0)
+ if (a == 0x1b && b == '[')
return (1);
- vtc_log(vl, 3, "No adm3a terminfo entry. (install ncurses-term ?)");
+ vtc_log(vl, 3, "No 'ansi' terminfo entry.");
return (0);
}
diff --git a/bin/varnishtest/vtc_process.c b/bin/varnishtest/vtc_process.c
index 84b31cc..dde798b 100644
--- a/bin/varnishtest/vtc_process.c
+++ b/bin/varnishtest/vtc_process.c
@@ -24,6 +24,9 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
+ *
+ * XXX:
+ * -ignore-stderr (otherwise output to stderr is fail)
*/
#include "config.h"
@@ -32,6 +35,7 @@
#include <sys/resource.h>
#include <sys/wait.h>
+#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
@@ -76,6 +80,15 @@ struct process {
pthread_t tp;
unsigned hasthread;
int status;
+
+ unsigned term_state;
+#define NTERMARG 10
+ int term_arg[NTERMARG];
+ int *term_ap;
+#define NLINES 24
+#define NCOLS 80
+ char *term_c[NLINES];
+ int term_x, term_y;
};
static VTAILQ_HEAD(, process) processes =
@@ -100,6 +113,7 @@ process_new(const char *name)
struct process *p;
struct vsb *vsb;
char buf[1024];
+ int i;
ALLOC_OBJ(p, PROCESS_MAGIC);
AN(p);
@@ -120,6 +134,12 @@ process_new(const char *name)
p->fd_term = -1;
VTAILQ_INSERT_TAIL(&processes, p, list);
+ for (i = 0; i < NLINES; i++) {
+ p->term_c[i] = malloc(NCOLS + 1);
+ AN(p->term_c[i]);
+ memset(p->term_c[i], ' ', NCOLS);
+ p->term_c[i][NCOLS] = '\0';
+ }
return (p);
}
@@ -162,7 +182,193 @@ process_undef(const struct process *p)
}
/**********************************************************************
- * Start the process thread
+ * Terminal emulation
+ */
+
+static void
+process_term_clear(const struct process *p)
+{
+ int i;
+
+ for (i = 0; i < NLINES; i++) {
+ memset(p->term_c[i], ' ', NCOLS);
+ p->term_c[i][NCOLS] = '\0';
+ }
+}
+
+static void
+process_screen_dump(const struct process *p)
+{
+ int i;
+
+ for (i = 0; i < NLINES; i++)
+ vtc_dump(p->vl, 3, "screen", p->term_c[i], NCOLS);
+}
+
+static void
+process_escape(struct process *p, int c, int n)
+{
+ int i;
+
+ for (i = 0; i < NTERMARG; i++)
+ if (!p->term_arg[i])
+ p->term_arg[i] = 1;
+ switch(c) {
+ case 'h':
+ if (p->term_arg[0] <= NLINES && p->term_arg[1] <= NCOLS) {
+ p->term_y = p->term_arg[0] - 1;
+ p->term_x = p->term_arg[1] - 1;
+ } else {
+ vtc_log(p->vl, 4, "ANSI H %d %d WRONG",
+ p->term_arg[0], p->term_arg[1]);
+ }
+ break;
+ case 'j':
+ if (p->term_arg[0] == 2) {
+ process_term_clear(p);
+ } else {
+ vtc_log(p->vl, 4, "ANSI J %d", p->term_arg[0]);
+ }
+ break;
+ default:
+ for (i = 0; i < n; i++)
+ vtc_log(p->vl, 4, "ANSI arg %d",
+ p->term_arg[i]);
+ vtc_log(p->vl, 4, "ANSI unk '%c'", c);
+ break;
+ }
+}
+
+static void
+process_scroll(struct process *p)
+{
+ int i;
+ char *l;
+
+ l = p->term_c[0];
+ for(i = 0; i < NLINES -1; i++)
+ p->term_c[i] = p->term_c[i + 1];
+ p->term_c[i] = l;
+ memset(l, ' ', NCOLS);
+}
+
+static void
+process_char(struct process *p, char c)
+{
+ assert(p->term_x < NCOLS);
+ assert(p->term_y < NLINES);
+ assert(p->term_state <= 3);
+ switch (c) {
+ case 0x00:
+ break;
+ case '\b':
+ if (p->term_x > 0)
+ p->term_x--;
+ break;
+ case '\t':
+ while(++p->term_x % 8)
+ continue;
+ if (p->term_x >= NCOLS) {
+ p->term_x = 0;
+ process_char(p, '\n');
+ }
+ break;
+ case '\n':
+ if (p->term_y == NLINES - 1)
+ process_scroll(p);
+ else
+ p->term_y++;
+ break;
+ case '\r':
+ p->term_x = 0;
+ break;
+ default:
+ if (c < ' ' || c > '~')
+ vtc_log(p->vl, 4, "ANSI CTRL 0x%02x", c);
+ else {
+ p->term_c[p->term_y][p->term_x] = c;
+ if (p->term_x == NCOLS - 1) {
+ p->term_x = 0;
+ process_char(p, '\n');
+ } else {
+ p->term_x++;
+ }
+ }
+ }
+}
+
+static void
+process_ansi(struct process *p, const char *b, const char *e)
+{
+
+ while (b < e) {
+ assert(p->term_x < NCOLS);
+ assert(p->term_y < NLINES);
+ assert(p->term_state <= 3);
+ switch (p->term_state) {
+ case 0:
+ if (*b == '\x1b')
+ p->term_state = 1;
+ else if (*(const uint8_t*)b == 0x9b)
+ p->term_state = 2;
+ else
+ process_char(p, *b);
+ b++;
+ break;
+ case 1:
+ if (*b++ == '[') {
+ p->term_state = 2;
+ } else {
+ vtc_log(p->vl, 4, "ANSI not [ 0x%x", b[-1]);
+ p->term_state = 0;
+ }
+ break;
+ case 2:
+ p->term_ap = p->term_arg;
+ memset(p->term_arg, 0, sizeof p->term_arg);
+ p->term_state = 3;
+ break;
+ case 3:
+ if (p->term_ap - p->term_arg >= NTERMARG) {
+ vtc_log(p->vl, 4, "ANSI too many ;");
+ p->term_state = 0;
+ b++;
+ continue;
+ }
+ if (isdigit(*b)) {
+ *p->term_ap *= 10;
+ *p->term_ap += *b++ - '0';
+ continue;
+ }
+ if (*b == ';') {
+ p->term_ap++;
+ p->term_state = 3;
+ b++;
+ continue;
+ }
+ if (islower(*b)) {
+ process_escape(p, *b++,
+ p->term_ap - p->term_arg);
+ p->term_state = 2;
+ } else if (isupper(*b)) {
+ process_escape(p, tolower(*b++),
+ p->term_ap - p->term_arg);
+ p->term_ap = p->term_arg;
+ p->term_state = 0;
+ } else {
+ vtc_log(p->vl, 4, "ANSI non-letter %c", *b);
+ p->term_state = 0;
+ b++;
+ }
+ break;
+ default:
+ WRONG("Wrong ansi state");
+ }
+ }
+}
+
+/**********************************************************************
+ * Data stream handling
*/
static int
@@ -196,6 +402,7 @@ process_stdout(const struct vev *ev, int what)
else if (p->log == 3)
vtc_hexdump(p->vl, 4, "stdout", buf, i);
(void)write(p->f_stdout, buf, i);
+ process_ansi(p, buf, buf + i);
return (0);
}
@@ -343,6 +550,10 @@ process_init_term(struct process *p, int fd)
vtc_log(p->vl, 4, "TCSAFLUSH %d %s", i, strerror(errno));
}
+/**********************************************************************
+ * Start the process thread
+ */
+
static void
process_start(struct process *p)
{
@@ -382,7 +593,7 @@ process_start(struct process *p)
p->pid = fork();
assert(p->pid >= 0);
if (p->pid == 0) {
- AZ(setenv("TERM", "adm3a", 1));
+ AZ(setenv("TERM", "ansi", 1));
AZ(unsetenv("TERMCAP"));
assert(dup2(slave, STDIN_FILENO) == STDIN_FILENO);
assert(dup2(slave, STDOUT_FILENO) == STDOUT_FILENO);
@@ -578,6 +789,9 @@ process_close(struct process *p)
* \-close
* Alias for "-kill HUP"
*
+ * \-screen_dump
+ * Dump the virtual screen into vtc_log
+ *
*/
void
@@ -680,6 +894,10 @@ cmd_process(CMD_ARGS)
av++;
continue;
}
+ if (!strcmp(*av, "-screen_dump")) {
+ process_screen_dump(p);
+ continue;
+ }
if (!strcmp(*av, "-close")) {
process_close(p);
continue;
More information about the varnish-commit
mailing list