mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-08-04 08:57:20 +00:00
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:
parent
6dae681515
commit
7ee5bb5583
@ -38,10 +38,10 @@
|
|||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
#include <lxc/error.h>
|
#include "error.h"
|
||||||
#include <lxc/lxc.h>
|
#include "lxc.h"
|
||||||
#include <lxc/log.h>
|
#include "log.h"
|
||||||
|
#include "mainloop.h"
|
||||||
#include "arguments.h"
|
#include "arguments.h"
|
||||||
|
|
||||||
lxc_log_define(lxc_console_ui, lxc_console);
|
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)
|
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);
|
ERROR("'%d' is not a tty", fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -132,21 +132,68 @@ static int setup_tios(int fd, struct termios *newtios, struct termios *oldtios)
|
|||||||
return 0;
|
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 main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int wait4q = 0;
|
int err, std_in = 1;
|
||||||
int err;
|
struct lxc_epoll_descr descr;
|
||||||
struct termios newtios, oldtios;
|
struct termios newtios, oldtios;
|
||||||
|
|
||||||
err = lxc_arguments_parse(&my_args, argc, argv);
|
err = lxc_arguments_parse(&my_args, argc, argv);
|
||||||
if (err)
|
if (err)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (lxc_log_init(my_args.log_file, my_args.log_priority,
|
err = lxc_log_init(my_args.log_file, my_args.log_priority,
|
||||||
my_args.progname, my_args.quiet))
|
my_args.progname, my_args.quiet);
|
||||||
|
if (err)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (setup_tios(0, &newtios, &oldtios)) {
|
err = setup_tios(0, &newtios, &oldtios);
|
||||||
|
if (err) {
|
||||||
ERROR("failed to setup tios");
|
ERROR("failed to setup tios");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -158,77 +205,47 @@ int main(int argc, char *argv[])
|
|||||||
fprintf(stderr, "\nType <Ctrl+%c q> to exit the console\n",
|
fprintf(stderr, "\nType <Ctrl+%c q> to exit the console\n",
|
||||||
'a' + my_args.escape - 1);
|
'a' + my_args.escape - 1);
|
||||||
|
|
||||||
if (setsid())
|
err = setsid();
|
||||||
|
if (err)
|
||||||
INFO("already group leader");
|
INFO("already group leader");
|
||||||
|
|
||||||
if (signal(SIGWINCH, sigwinch) == SIG_ERR) {
|
if (signal(SIGWINCH, sigwinch) == SIG_ERR) {
|
||||||
SYSERROR("failed to set SIGWINCH handler");
|
SYSERROR("failed to set SIGWINCH handler");
|
||||||
return -1;
|
err = -1;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
winsz();
|
winsz();
|
||||||
|
|
||||||
err = 0;
|
err = lxc_mainloop_open(&descr);
|
||||||
|
if (err) {
|
||||||
/* let's proxy the tty */
|
ERROR("failed to create mainloop");
|
||||||
for (;;) {
|
goto out;
|
||||||
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_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:
|
out:
|
||||||
/* Restore previous terminal parameter */
|
/* Restore previous terminal parameter */
|
||||||
tcsetattr(0, TCSAFLUSH, &oldtios);
|
tcsetattr(0, TCSAFLUSH, &oldtios);
|
||||||
@ -239,8 +256,4 @@ out:
|
|||||||
close(master);
|
close(master);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
out_err:
|
|
||||||
err = -1;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user