static void winch_handler(int sig) { struct winsize winp; if(!ioctl( 0, TIOCGWINSZ, &winp)) { conf.row = winp.ws_row; conf.col = winp.ws_col; console_winch(conf.s, conf.ifindex, conf.row, conf.col); } }
/* @ttyno: 0 is tty1, 1 is tty2 etc. * * Note tty1 is used for console */ int do_console_attach(vps_handler *h, envid_t veid, int ttyno) { struct vzctl_ve_configure c; int pid, status; char buf; const char esc = 27; const char enter = 13; int new_line = 1; int ret = VZ_SYSTEM_ERROR; if (ttyno < 0) /* undef */ ttyno = 0; /* tty1 aka console by default */ child_term = 0; c.veid = veid; c.key = VE_CONFIGURE_OPEN_TTY; c.val = ttyno; c.size = 0; tty = ioctl(h->vzfd, VZCTL_VE_CONFIGURE, &c); if (tty < 0) { fprintf(stderr, "Error in VE_CONFIGURE_OPEN_TTY: %s\n", strerror(errno)); return VZ_SYSTEM_ERROR; } signal(SIGCHLD, child_handler); signal(SIGWINCH, console_winch); console_winch(0); fprintf(stderr, "Attached to CT %d (ESC . to detach)\n", veid); if ((pid = fork()) < 0) { fprintf(stderr, "Unable to fork: %s\n", strerror(errno)); return VZ_RESOURCE_ERROR; } if (pid == 0) { char bigbuf[4096]; ssize_t nread; while (1) { if ((nread = read(tty, &bigbuf, sizeof bigbuf)) <= 0) { if (errno == EINTR || errno == EAGAIN) continue; if (nread < 0) err(1, "tty read error: %m"); exit(nread < 0 ? 2 : 0 ); } if (write(1, &bigbuf, nread) < 0) { err(1, "stdout write error: %m"); exit(3); } } exit(0); } raw_on(); #define TREAD(buf) \ do { \ if (read(0, &buf, sizeof buf) <= 0) { \ warn("stdin read error"); \ goto err; \ } \ } while (0) #define TWRITE(buf) \ do { \ if (write(tty, &buf, sizeof buf) <= 0) { \ warn("tty write error"); \ goto err; \ } \ } while (0) while (!child_term) { TREAD(buf); if (buf == esc && new_line) { TREAD(buf); switch (buf) { case '.': goto out; case '!': sak(); continue; default: TWRITE(esc); break; } } TWRITE(buf); new_line = (buf == enter); } out: ret = 0; err: kill(pid, SIGKILL); while (waitpid(pid, &status, 0) == -1) if (errno != EINTR) break; raw_off(); fprintf(stderr, "\nDetached from CT %d\n", veid); return ret; }