]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
simplify pty allocation and implement pty logging 953/head
authorChristian Brauner <christian.brauner@mailbox.org>
Fri, 8 Apr 2016 13:53:36 +0000 (15:53 +0200)
committerChristian Brauner <christian.brauner@mailbox.org>
Fri, 8 Apr 2016 14:01:55 +0000 (16:01 +0200)
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 <christian.brauner@mailbox.org>
src/lxc/console.c
src/lxc/console.h
src/lxc/lxc_attach.c
src/lxc/start.c

index 2ce3cc4cced38b2a58c5f2653be51b243d09ae2a..f8741728b5d4546e5a65a8f494a011945ab64180 100644 (file)
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <sys/epoll.h>
-#include <sys/types.h>
 #include <termios.h>
 #include <unistd.h>
+#include <sys/epoll.h>
+#include <sys/types.h>
 
 #include <lxc/lxccontainer.h>
 
@@ -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) {
index d3ccd8b0c45e6d0c823fb8ede7bfa3db4b417b98..fefdb19e2c962a436ab26550b00f02b7bb704b9c 100644 (file)
@@ -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.
index cdc56d6c8c4cb912bdcb31916cef8a1690dc2d29..f02ef2621a14482d82c3559ba58dd8c877d52c50 100644 (file)
@@ -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) {
index 5be0077bf46d26a9c9b67ded7a8a9b8dffd2da88..d9d5814b5b5e314b0e790415c0641c3983b2f9e8 100644 (file)
@@ -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;
        }