From da41561c72067a5e109e8c5482dbeb4131641dc2 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 8 Apr 2016 15:53:36 +0200 Subject: [PATCH] simplify pty allocation and implement pty logging lxc-attach allocated a pty in a manner that relied on ts->stdinfd and ts->stdoutfd to be set. We had to resort to a trick to get it working when output is redirected. The new implementation gets rid of the black magic and also simplifies the code. This commit also implements pty logging for lxc-attach. Users will now be able to log commands and corresponding output to a file given that lxc-attach allocates a pty. Signed-off-by: Christian Brauner --- src/lxc/console.c | 12 ++++---- src/lxc/console.h | 2 +- src/lxc/lxc_attach.c | 71 +++++++------------------------------------- src/lxc/start.c | 2 +- 4 files changed, 20 insertions(+), 67 deletions(-) diff --git a/src/lxc/console.c b/src/lxc/console.c index 2ce3cc4cc..f8741728b 100644 --- a/src/lxc/console.c +++ b/src/lxc/console.c @@ -27,10 +27,10 @@ #include #include #include -#include -#include #include #include +#include +#include #include @@ -163,6 +163,9 @@ static int lxc_console_cb_con(int fd, uint32_t events, void *data, char buf[1024]; int r,w; + if (events & EPOLLHUP) + return 1; + w = r = read(fd, buf, sizeof(buf)); if (r < 0) { SYSERROR("failed to read"); @@ -212,10 +215,9 @@ static void lxc_console_mainloop_add_peer(struct lxc_console *console) } } -int lxc_console_mainloop_add(struct lxc_epoll_descr *descr, - struct lxc_handler *handler) +extern int lxc_console_mainloop_add(struct lxc_epoll_descr *descr, + struct lxc_conf *conf) { - struct lxc_conf *conf = handler->conf; struct lxc_console *console = &conf->console; if (conf->is_execute) { diff --git a/src/lxc/console.h b/src/lxc/console.h index d3ccd8b0c..fefdb19e2 100644 --- a/src/lxc/console.h +++ b/src/lxc/console.h @@ -102,7 +102,7 @@ extern void lxc_console_free(struct lxc_conf *conf, int fd); /* * Register pty event handlers in an open mainloop */ -extern int lxc_console_mainloop_add(struct lxc_epoll_descr *, struct lxc_handler *); +extern int lxc_console_mainloop_add(struct lxc_epoll_descr *, struct lxc_conf *); /* * Handle SIGWINCH events on the allocated ptys. diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c index cdc56d6c8..f02ef2621 100644 --- a/src/lxc/lxc_attach.c +++ b/src/lxc/lxc_attach.c @@ -64,6 +64,7 @@ static const struct option my_longopts[] = { {"keep-env", no_argument, 0, 501}, {"keep-var", required_argument, 0, 502}, {"set-var", required_argument, 0, 'v'}, + {"pty-log", required_argument, 0, 'L'}, LXC_COMMON_OPTIONS }; @@ -149,6 +150,9 @@ static int my_parser(struct lxc_arguments* args, int c, char* arg) return -1; } break; + case 'L': + args->console_log = arg; + break; } return 0; @@ -191,6 +195,8 @@ Options :\n\ --keep-env Keep all current environment variables. This\n\ is the current default behaviour, but is likely to\n\ change in the future.\n\ + -L, --pty-log=FILE\n\ + Log pty output to FILE\n\ -v, --set-var Set an additional variable that is seen by the\n\ attached program in the container. May be specified\n\ multiple times.\n\ @@ -254,7 +260,10 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int * conf = c->lxc_conf; free(conf->console.log_path); - conf->console.log_path = NULL; + if (my_args.console_log) + conf->console.log_path = strdup(my_args.console_log); + else + conf->console.log_path = NULL; /* In the case of lxc-attach our peer pty will always be the current * controlling terminal. We clear whatever was set by the user for @@ -272,39 +281,6 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int * if (lxc_console_create(conf) < 0) return -1; ts = conf->console.tty_state; - /* - * We need to make sure that the ouput that is produced inside the - * container is received on the host. Suppose we want to run - * - * lxc-attach -n a -- /bin/sh -c 'hostname >&2' > /dev/null - * - * This command produces output on stderr inside the container. On the - * host we close stdout by redirecting it to /dev/null. But stderr is, - * as expected, still connected to a tty. We receive the output produced - * on stderr in the container on stderr on the host. - * - * For the command - * - * lxc-attach -n a -- /bin/sh -c 'hostname >&2' 2> /dev/null - * - * the logic is analogous but because we now have closed stderr on the - * host no output will be received. - * - * Finally, imagine a more complicated case - * - * lxc-attach -n a -- /bin/sh -c 'echo OUT; echo ERR >&2' > /tmp/out 2> /tmp/err - * - * Here, we produce output in the container on stdout and stderr. On the - * host we redirect stdout and stderr to files. Because of that stdout - * and stderr are not dup2()ed. Thus, they are not connected to a pty - * and output on stdout and stderr is redirected to the corresponding - * files as expected. - */ - if (!isatty(STDOUT_FILENO) && isatty(STDERR_FILENO)) - ts->stdoutfd = STDERR_FILENO; - else - ts->stdoutfd = STDOUT_FILENO; - conf->console.descr = &descr; /* Shift ttys to container. */ @@ -325,33 +301,8 @@ static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int * goto err2; } - /* Register sigwinch handler in mainloop. When ts->sigfd == -1 it means - * we weren't able to install a sigwinch handler in - * lxc_console_create(). We don't consider this fatal and just move on. - */ - if (ts->sigfd != -1) { - ret = lxc_mainloop_add_handler(&descr, ts->sigfd, - lxc_console_cb_sigwinch_fd, ts); - if (ret) { - ERROR("failed to add handler for SIGWINCH fd"); - goto err3; - } - } - - /* Register i/o callbacks in mainloop. */ - ret = lxc_mainloop_add_handler(&descr, ts->stdinfd, - lxc_console_cb_tty_stdin, ts); - if (ret) { - ERROR("failed to add handler for stdinfd"); - goto err3; - } - - ret = lxc_mainloop_add_handler(&descr, ts->masterfd, - lxc_console_cb_tty_master, ts); - if (ret) { - ERROR("failed to add handler for masterfd"); + if (lxc_console_mainloop_add(&descr, conf) < 0) goto err3; - } ret = lxc_mainloop(&descr, -1); if (ret) { diff --git a/src/lxc/start.c b/src/lxc/start.c index 5be0077bf..d9d5814b5 100644 --- a/src/lxc/start.c +++ b/src/lxc/start.c @@ -365,7 +365,7 @@ int lxc_poll(const char *name, struct lxc_handler *handler) goto out_mainloop_open; } - if (lxc_console_mainloop_add(&descr, handler)) { + if (lxc_console_mainloop_add(&descr, handler->conf)) { ERROR("failed to add console handler to mainloop"); goto out_mainloop_open; } -- 2.47.2