use a mainloop for the console

Use the mainloop to manage io of the console.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
This commit is contained in:
Daniel Lezcano 2010-02-24 10:57:42 +01:00 committed by Daniel Lezcano
parent 6dae681515
commit 7ee5bb5583

View File

@ -38,10 +38,10 @@
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <lxc/error.h>
#include <lxc/lxc.h>
#include <lxc/log.h>
#include "error.h"
#include "lxc.h"
#include "log.h"
#include "mainloop.h"
#include "arguments.h"
lxc_log_define(lxc_console_ui, lxc_console);
@ -102,7 +102,7 @@ static void sigwinch(int sig)
static int setup_tios(int fd, struct termios *newtios, struct termios *oldtios)
{
if (isatty(fd)) {
if (!isatty(fd)) {
ERROR("'%d' is not a tty", fd);
return -1;
}
@ -132,21 +132,68 @@ static int setup_tios(int fd, struct termios *newtios, struct termios *oldtios)
return 0;
}
static int stdin_handler(int fd, void *data, struct lxc_epoll_descr *descr)
{
static int wait4q = 0;
int *peer = (int *)data;
char c;
if (read(0, &c, 1) < 0) {
SYSERROR("failed to read");
return 1;
}
/* we want to exit the console with Ctrl+a q */
if (c == my_args.escape) {
wait4q = !wait4q;
return 0;
}
if (c == 'q' && wait4q)
return 1;
wait4q = 0;
if (write(*peer, &c, 1) < 0) {
SYSERROR("failed to write");
return 1;
}
return 0;
}
static int master_handler(int fd, void *data, struct lxc_epoll_descr *descr)
{
char buf[1024];
int *peer = (int *)data;
int r;
r = read(fd, buf, sizeof(buf));
if (r < 0) {
SYSERROR("failed to read");
return 1;
}
write(*peer, buf, r);
return 0;
}
int main(int argc, char *argv[])
{
int wait4q = 0;
int err;
int err, std_in = 1;
struct lxc_epoll_descr descr;
struct termios newtios, oldtios;
err = lxc_arguments_parse(&my_args, argc, argv);
if (err)
return -1;
if (lxc_log_init(my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet))
err = lxc_log_init(my_args.log_file, my_args.log_priority,
my_args.progname, my_args.quiet);
if (err)
return -1;
if (setup_tios(0, &newtios, &oldtios)) {
err = setup_tios(0, &newtios, &oldtios);
if (err) {
ERROR("failed to setup tios");
return -1;
}
@ -158,77 +205,47 @@ int main(int argc, char *argv[])
fprintf(stderr, "\nType <Ctrl+%c q> to exit the console\n",
'a' + my_args.escape - 1);
if (setsid())
err = setsid();
if (err)
INFO("already group leader");
if (signal(SIGWINCH, sigwinch) == SIG_ERR) {
SYSERROR("failed to set SIGWINCH handler");
return -1;
err = -1;
goto out;
}
winsz();
err = 0;
/* let's proxy the tty */
for (;;) {
struct pollfd pfd[2] = {
{ .fd = 0,
.events = POLLIN|POLLPRI,
.revents = 0 },
{ .fd = master,
.events = POLLIN|POLLPRI,
.revents = 0 },
};
if (poll(pfd, 2, -1) < 0) {
if (errno == EINTR)
continue;
SYSERROR("failed to poll");
goto out_err;
}
/* read the "stdin" and write that to the master
*/
if (pfd[0].revents & POLLIN) {
char c;
if (read(0, &c, 1) < 0) {
SYSERROR("failed to read");
goto out_err;
}
/* we want to exit the console with Ctrl+a q */
if (c == my_args.escape) {
wait4q = !wait4q;
continue;
}
if (c == 'q' && wait4q)
goto out;
wait4q = 0;
if (write(master, &c, 1) < 0) {
SYSERROR("failed to write");
goto out_err;
}
}
/* other side has closed the connection */
if (pfd[1].revents & POLLHUP)
goto out;
/* read the master and write to "stdout" */
if (pfd[1].revents & POLLIN) {
char buf[1024];
int r;
r = read(master, buf, sizeof(buf));
if (r < 0) {
SYSERROR("failed to read");
goto out_err;
}
write(1, buf, r);
}
err = lxc_mainloop_open(&descr);
if (err) {
ERROR("failed to create mainloop");
goto out;
}
err = lxc_mainloop_add_handler(&descr, 0, stdin_handler, &master);
if (err) {
ERROR("failed to add handler for the stdin");
goto out_mainloop_open;
}
err = lxc_mainloop_add_handler(&descr, master, master_handler, &std_in);
if (err) {
ERROR("failed to add handler for the master");
goto out_mainloop_open;
}
err = lxc_mainloop(&descr);
if (err) {
ERROR("mainloop returned an error");
goto out_mainloop_open;
}
err = 0;
out_mainloop_open:
lxc_mainloop_close(&descr);
out:
/* Restore previous terminal parameter */
tcsetattr(0, TCSAFLUSH, &oldtios);
@ -239,8 +256,4 @@ out:
close(master);
return err;
out_err:
err = -1;
goto out;
}