diff --git a/test.c b/test.c index 5897190..3ef7bde 100644 --- a/test.c +++ b/test.c @@ -13,7 +13,7 @@ void disp(struct vt100_headless *vt100) struct vt100_term *term; const char **lines; - term = vt100->term->user_data; + term = vt100->term; lines = vt100_dump(term); for (y = 0; y < term->height; ++y) { diff --git a/vt100.c b/vt100.c index 7da9e41..0a73eac 100644 --- a/vt100.c +++ b/vt100.c @@ -170,7 +170,7 @@ static void set(struct vt100_term *headless_term, } -char get(struct vt100_term *vt100, unsigned int x, unsigned int y) +char vt100_get(struct vt100_term *vt100, unsigned int x, unsigned int y) { if (y < vt100->margin_top || y > vt100->margin_bottom) return vt100->frozen_screen[FROZEN_SCREEN_PTR(vt100, x, y)]; @@ -895,9 +895,9 @@ const char **vt100_dump(struct vt100_term *vt100) return (const char **)vt100->lines; } -struct terminal *vt100_init(void (*unimplemented)(struct terminal* term_emul, char *seq, char chr)) +/*TODO: put spaces instead of \0 in frozen_screen */ +struct vt100_term *vt100_init(void (*unimplemented)(struct terminal* term_emul, char *seq, char chr)) { - struct terminal *term; struct vt100_term *vt100; vt100 = calloc(1, sizeof(*vt100)); @@ -911,7 +911,7 @@ struct terminal *vt100_init(void (*unimplemented)(struct terminal* term_emul, ch sizeof(*vt100->frozen_screen)); vt100->tabulations = malloc(132); if (vt100->tabulations == NULL) - return NULL; /* Need to free before returning ... */ + return NULL; /*TODO: Need to free before returning ... */ vt100->margin_top = 0; vt100->margin_bottom = vt100->height - 1; vt100->selected_charset = 0; @@ -919,32 +919,32 @@ struct terminal *vt100_init(void (*unimplemented)(struct terminal* term_emul, ch vt100->y = 0; vt100->modes = MASK_DECANM; vt100->top_line = 0; - term = terminal_init(); - term->width = 80; - term->height = 24; - term->write = vt100_write; - term->callbacks.csi.f = HVP; - term->callbacks.csi.K = EL; - term->callbacks.csi.c = DA; - term->callbacks.csi.h = SM; - term->callbacks.csi.l = RM; - term->callbacks.csi.J = ED; - term->callbacks.csi.H = CUP; - term->callbacks.csi.C = CUF; - term->callbacks.csi.B = CUD; - term->callbacks.csi.r = DECSTBM; - term->callbacks.csi.m = SGR; - term->callbacks.csi.A = CUU; - term->callbacks.csi.g = TBC; - term->callbacks.esc.H = HTS; - term->callbacks.csi.D = CUB; - term->callbacks.esc.E = NEL; - term->callbacks.esc.D = IND; - term->callbacks.esc.M = RI; - term->callbacks.esc.n8 = DECRC; - term->callbacks.esc.n7 = DECSC; - term->callbacks.hash.n8 = DECALN; - term->user_data = vt100; - term->unimplemented = unimplemented; - return term; + vt100->terminal = terminal_init(); + vt100->terminal->user_data = vt100; + vt100->terminal->width = 80; + vt100->terminal->height = 24; + vt100->terminal->write = vt100_write; + vt100->terminal->callbacks.csi.f = HVP; + vt100->terminal->callbacks.csi.K = EL; + vt100->terminal->callbacks.csi.c = DA; + vt100->terminal->callbacks.csi.h = SM; + vt100->terminal->callbacks.csi.l = RM; + vt100->terminal->callbacks.csi.J = ED; + vt100->terminal->callbacks.csi.H = CUP; + vt100->terminal->callbacks.csi.C = CUF; + vt100->terminal->callbacks.csi.B = CUD; + vt100->terminal->callbacks.csi.r = DECSTBM; + vt100->terminal->callbacks.csi.m = SGR; + vt100->terminal->callbacks.csi.A = CUU; + vt100->terminal->callbacks.csi.g = TBC; + vt100->terminal->callbacks.esc.H = HTS; + vt100->terminal->callbacks.csi.D = CUB; + vt100->terminal->callbacks.esc.E = NEL; + vt100->terminal->callbacks.esc.D = IND; + vt100->terminal->callbacks.esc.M = RI; + vt100->terminal->callbacks.esc.n8 = DECRC; + vt100->terminal->callbacks.esc.n7 = DECSC; + vt100->terminal->callbacks.hash.n8 = DECALN; + vt100->terminal->unimplemented = unimplemented; + return vt100; } diff --git a/vt100.h b/vt100.h index 53ff524..3663d70 100644 --- a/vt100.h +++ b/vt100.h @@ -46,6 +46,7 @@ */ struct vt100_term { + struct terminal *terminal; unsigned int width; unsigned int height; unsigned int x; @@ -63,7 +64,7 @@ struct vt100_term char *lines[80]; }; -struct terminal *vt100_init(void (*unimplemented)(struct terminal* term_emul, char *seq, char chr)); -char get(struct vt100_term *vt100, unsigned int x, unsigned int y); +struct vt100_term *vt100_init(void (*unimplemented)(struct terminal* term_emul, char *seq, char chr)); +char vt100_get(struct vt100_term *vt100, unsigned int x, unsigned int y); const char **vt100_dump(struct vt100_term *vt100); #endif diff --git a/vt100_headless.c b/vt100_headless.c new file mode 100644 index 0000000..eca0513 --- /dev/null +++ b/vt100_headless.c @@ -0,0 +1,131 @@ +#define _XOPEN_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include "vt100_headless.h" +#include "vt100.h" + +struct vt100_headless *vt100_headless_init(void) +{ + return malloc(sizeof(struct vt100_headless)); +} + +static void set_non_canonical(struct vt100_headless *this, int fd) +{ + struct termios termios; + + ioctl(fd, TCGETS, &this->backup); + ioctl(fd, TCGETS, &termios); + termios.c_iflag |= ICANON; + termios.c_cc[VMIN] = 1; + termios.c_cc[VTIME] = 0; + ioctl(fd, TCSETS, &termios); +} + +static void restore_termios(struct vt100_headless *this, int fd) +{ + ioctl(fd, TCSETS, &this->backup); +} + +/* static void debug(struct vt100_headless *this, char *title) */ +/* { */ +/* unsigned int argc; */ + +/* fprintf(stderr, "%s ", title); */ +/* for (argc = 0; argc < this->term->argc; ++argc) */ +/* { */ +/* fprintf(stderr, "%d", this->term->argv[argc]); */ +/* if (argc != this->term->argc - 1) */ +/* fprintf(stderr, ", "); */ +/* } */ +/* fprintf(stderr, "\n"); */ +/* } */ + +static void strdump(char *str) +{ + while (*str != '\0') + { + if (*str >= ' ' && *str <= '~') + fprintf(stderr, "%c", *str); + else + fprintf(stderr, "\\0%o", *str); + str += 1; + } + fprintf(stderr, "\n"); +} + +static int main_loop(struct vt100_headless *this) +{ + char buffer[4096]; + fd_set rfds; + int retval; + ssize_t read_size; + + while (42) + { + FD_ZERO(&rfds); + FD_SET(this->master, &rfds); + FD_SET(0, &rfds); + retval = select(this->master + 1, &rfds, NULL, NULL, NULL); + if (retval == -1) + { + perror("select()"); + } + if (FD_ISSET(0, &rfds)) + { + read_size = read(0, &buffer, 4096); + if (read_size == -1) + { + perror("read"); + return EXIT_FAILURE; + } + buffer[read_size] = '\0'; + write(this->master, buffer, read_size); + } + if (FD_ISSET(this->master, &rfds)) + { + read_size = read(this->master, &buffer, 4096); + if (read_size == -1) + { + perror("read"); + return EXIT_FAILURE; + } + buffer[read_size] = '\0'; + strdump(buffer); + terminal_read_str(this->term->terminal, buffer); + this->changed(this); + } + } +} + +void vt100_headless_fork(struct vt100_headless *this, + const char *progname, + char *const argv[]) +{ + int child; + struct winsize winsize; + + set_non_canonical(this, 0); + winsize.ws_row = 24; + winsize.ws_col = 24; + child = forkpty(&this->master, NULL, NULL, NULL); + if (child == CHILD) + { + setsid(); + putenv("TERM=vt100"); + execvp(progname, argv); + return ; + } + else + { + this->term = vt100_init(terminal_default_unimplemented); + ioctl(this->master, TIOCSWINSZ, &winsize); + this->term->terminal->fd = this->master; + main_loop(this); + } + restore_termios(this, 0); +} diff --git a/vt100_headless.h b/vt100_headless.h new file mode 100644 index 0000000..733b9d0 --- /dev/null +++ b/vt100_headless.h @@ -0,0 +1,18 @@ +#ifndef __VT100_HEADLESS_H__ +#define __VT100_HEADLESS_H__ + +#define CHILD 0 + +struct vt100_headless +{ + int master; + struct termios backup; + struct vt100_term *term; + void (*changed)(struct vt100_headless *this); +}; + + +void vt100_headless_fork(struct vt100_headless *this, const char *progname, char *const argv[]); +struct vt100_headless *vt100_headless_init(void); + +#endif