]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
attach: move pty allocation into api
authorChristian Brauner <christian.brauner@ubuntu.com>
Sun, 24 Dec 2017 18:25:34 +0000 (19:25 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Tue, 9 Jan 2018 12:20:23 +0000 (13:20 +0100)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
doc/lxc-attach.sgml.in
src/lxc/attach.c
src/lxc/attach_options.h
src/lxc/tools/lxc_attach.c
src/tests/attach.c
src/tests/lxc-test-lxc-attach

index 7535bb11472d43db5356e6a6f1f6b36a03a20a9b..713a30e7fbc921c122e303b3a2f5713f4fe09e46 100644 (file)
@@ -58,7 +58,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
       <arg choice="opt">-R, --remount-sys-proc</arg>
       <arg choice="opt">--keep-env</arg>
       <arg choice="opt">--clear-env</arg>
-      <arg choice="opt">-L, --pty-log <replaceable>file</replaceable></arg>
       <arg choice="opt">-v, --set-var <replaceable>variable</replaceable></arg>
       <arg choice="opt">--keep-var <replaceable>variable</replaceable></arg>
       <arg choice="opt">-- <replaceable>command</replaceable></arg>
@@ -256,22 +255,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
        </listitem>
       </varlistentry>
 
-      <varlistentry>
-       <term>
-         <option>-L, --pty-log <replaceable>file</replaceable></option>
-       </term>
-       <listitem>
-         <para>
-       Specify a file where the output of <command>lxc-attach</command> will be
-       logged.
-         </para>
-         <para>
-           <emphasis>Important:</emphasis>  When a standard file descriptor
-           does not refer to a pty output produced on it will not be logged.
-         </para>
-       </listitem>
-      </varlistentry>
-
       <varlistentry>
        <term>
          <option>-v, --set-var <replaceable>variable</replaceable></option>
index b6f290ad394ed1251b8e62e4395bdb23d78cd88d..34bdf91455fbc3b3cd3473211681cc3593c04deb 100644 (file)
@@ -66,6 +66,7 @@
 #include "lsm/lsm.h"
 #include "lxclock.h"
 #include "lxcseccomp.h"
+#include "mainloop.h"
 #include "namespace.h"
 #include "utils.h"
 
@@ -819,12 +820,30 @@ static signed long get_personality(const char *name, const char *lxcpath)
 
 struct attach_clone_payload {
        int ipc_socket;
+       int pty_fd;
        lxc_attach_options_t *options;
        struct lxc_proc_context_info *init_ctx;
        lxc_attach_exec_t exec_function;
        void *exec_payload;
 };
 
+static void lxc_put_attach_clone_payload(struct attach_clone_payload *p)
+{
+       if (p->ipc_socket >= 0) {
+               shutdown(p->ipc_socket, SHUT_RDWR);
+               close(p->ipc_socket);
+               p->ipc_socket = -EBADF;
+       }
+
+       if (p->pty_fd >= 0) {
+               close(p->pty_fd);
+               p->pty_fd = -EBADF;
+       }
+
+       if (p->init_ctx)
+               lxc_proc_put_context_info(p->init_ctx);
+}
+
 static int attach_child_main(struct attach_clone_payload *payload)
 {
        int fd, lsm_fd, ret;
@@ -961,7 +980,8 @@ static int attach_child_main(struct attach_clone_payload *payload)
        }
        shutdown(payload->ipc_socket, SHUT_RDWR);
        close(payload->ipc_socket);
-       payload->ipc_socket = -1;
+       payload->ipc_socket = -EBADF;
+       lxc_proc_put_context_info(init_ctx);
 
        /* The following is done after the communication socket is shut down.
         * That way, all errors that might (though unlikely) occur up until this
@@ -1011,19 +1031,107 @@ static int attach_child_main(struct attach_clone_payload *payload)
                }
        }
 
+       if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
+               ret = lxc_login_pty(payload->pty_fd);
+               if (ret < 0) {
+                       SYSERROR("Failed to prepare pty file descriptor %d", payload->pty_fd);
+                       goto on_error;
+               }
+               TRACE("Prepared pty file descriptor %d", payload->pty_fd);
+       }
+
        /* We're done, so we can now do whatever the user intended us to do. */
        rexit(payload->exec_function(payload->exec_payload));
 
 on_error:
-       if (payload->ipc_socket >= 0) {
-               shutdown(payload->ipc_socket, SHUT_RDWR);
-               close(payload->ipc_socket);
-               payload->ipc_socket = -1;
-       }
-       lxc_proc_put_context_info(init_ctx);
+       lxc_put_attach_clone_payload(payload);
        rexit(EXIT_FAILURE);
 }
 
+static int lxc_attach_pty(struct lxc_conf *conf, struct lxc_console *pty)
+{
+       int ret;
+
+       lxc_pty_init(pty);
+
+       ret = lxc_pty_create(pty);
+       if (ret < 0) {
+               SYSERROR("Failed to create pty");
+               return -1;
+       }
+
+       /* Shift ttys to container. */
+       ret = lxc_pty_map_ids(conf, pty);
+       if (ret < 0) {
+               ERROR("Failed to shift pty");
+               goto on_error;
+       }
+
+       return 0;
+
+on_error:
+       lxc_console_delete(pty);
+       lxc_pty_conf_free(pty);
+       return -1;
+}
+
+static int lxc_attach_pty_mainloop_init(struct lxc_console *pty,
+                                       struct lxc_epoll_descr *descr)
+{
+       int ret;
+
+       ret = lxc_mainloop_open(descr);
+       if (ret < 0) {
+               ERROR("Failed to create mainloop");
+               return -1;
+       }
+
+       ret = lxc_console_mainloop_add(descr, pty);
+       if (ret < 0) {
+               ERROR("Failed to add handlers to mainloop");
+               lxc_mainloop_close(descr);
+               return -1;
+       }
+
+       return 0;
+}
+
+static inline void lxc_attach_pty_close_master(struct lxc_console *pty)
+{
+       if (pty->master < 0)
+               return;
+
+       close(pty->master);
+       pty->master = -EBADF;
+}
+
+static inline void lxc_attach_pty_close_slave(struct lxc_console *pty)
+{
+       if (pty->slave < 0)
+               return;
+
+       close(pty->slave);
+       pty->slave = -EBADF;
+}
+
+static inline void lxc_attach_pty_close_peer(struct lxc_console *pty)
+{
+       if (pty->peer < 0)
+               return;
+
+       close(pty->peer);
+       pty->peer = -EBADF;
+}
+
+static inline void lxc_attach_pty_close_log(struct lxc_console *pty)
+{
+       if (pty->log_fd < 0)
+               return;
+
+       close(pty->log_fd);
+       pty->log_fd = -EBADF;
+}
+
 int lxc_attach(const char *name, const char *lxcpath,
               lxc_attach_exec_t exec_function, void *exec_payload,
               lxc_attach_options_t *options, pid_t *attached_process)
@@ -1032,8 +1140,9 @@ int lxc_attach(const char *name, const char *lxcpath,
        int ipc_sockets[2];
        char *cwd, *new_cwd;
        signed long personality;
-       pid_t attached_pid, expected, init_pid, pid;
+       pid_t attached_pid, init_pid, pid;
        struct lxc_proc_context_info *init_ctx;
+       struct lxc_console pty;
        struct attach_clone_payload payload = {0};
 
        ret = access("/proc/self/ns", X_OK);
@@ -1150,6 +1259,18 @@ int lxc_attach(const char *name, const char *lxcpath,
                return -1;
        }
 
+       if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
+               ret = lxc_attach_pty(init_ctx->container->lxc_conf, &pty);
+               if (ret < 0) {
+                       ERROR("Failed to allocate pty");
+                       free(cwd);
+                       lxc_proc_put_context_info(init_ctx);
+                       return -1;
+               }
+
+               pty.log_fd = options->log_fd;
+       }
+
        /* Create a socket pair for IPC communication; set SOCK_CLOEXEC in order
         * to make sure we don't irritate other threads that want to fork+exec
         * away
@@ -1210,13 +1331,16 @@ int lxc_attach(const char *name, const char *lxcpath,
        }
 
        if (pid) {
+               int ret_parent = -1;
                pid_t to_cleanup_pid = pid;
+               struct lxc_epoll_descr descr = {0};
 
-               /* Initial thread, we close the socket that is for the
-                * subprocesses.
-                */
+               /* close unneeded file descriptors */
                close(ipc_sockets[1]);
                free(cwd);
+               lxc_proc_close_ns_fd(init_ctx);
+               if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY)
+                       lxc_attach_pty_close_slave(&pty);
 
                /* Attach to cgroup, if requested. */
                if (options->attach_flags & LXC_ATTACH_MOVE_TO_CGROUP) {
@@ -1227,21 +1351,30 @@ int lxc_attach(const char *name, const char *lxcpath,
                }
 
                /* Setup resource limits */
-               if (!lxc_list_empty(&init_ctx->container->lxc_conf->limits))
-                       if (setup_resource_limits(&init_ctx->container->lxc_conf->limits, pid) < 0)
+               if (!lxc_list_empty(&init_ctx->container->lxc_conf->limits)) {
+                       ret = setup_resource_limits(&init_ctx->container->lxc_conf->limits, pid);
+                       if (ret < 0)
+                               goto on_error;
+               }
+
+               if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
+                       ret = lxc_attach_pty_mainloop_init(&pty, &descr);
+                       if (ret < 0)
                                goto on_error;
+                       TRACE("Initalized pty mainloop");
+               }
 
                /* Let the child process know to go ahead. */
                status = 0;
                ret = lxc_write_nointr(ipc_sockets[0], &status, sizeof(status));
                if (ret != sizeof(status))
-                       goto on_error;
+                       goto close_mainloop;
                TRACE("Told intermediate process to start initializing");
 
                /* Get pid of attached process from intermediate process. */
                ret = lxc_read_nointr(ipc_sockets[0], &attached_pid, sizeof(attached_pid));
                if (ret != sizeof(attached_pid))
-                       goto on_error;
+                       goto close_mainloop;
                TRACE("Received pid %d of attached process in parent pid namespace", attached_pid);
 
                /* Ignore SIGKILL (CTRL-C) and SIGQUIT (CTRL-\) - issue #313. */
@@ -1253,7 +1386,7 @@ int lxc_attach(const char *name, const char *lxcpath,
                /* Reap intermediate process. */
                ret = wait_for_pid(pid);
                if (ret < 0)
-                       goto on_error;
+                       goto close_mainloop;
                TRACE("Intermediate process %d exited", pid);
 
                /* We will always have to reap the attached process now. */
@@ -1269,7 +1402,7 @@ int lxc_attach(const char *name, const char *lxcpath,
                        on_exec = options->attach_flags & LXC_ATTACH_LSM_EXEC ? 1 : 0;
                        labelfd = lsm_open(attached_pid, on_exec);
                        if (labelfd < 0)
-                               goto on_error;
+                               goto close_mainloop;
                        TRACE("Opened LSM label file descriptor %d", labelfd);
 
                        /* Send child fd of the LSM security module to write to. */
@@ -1277,45 +1410,66 @@ int lxc_attach(const char *name, const char *lxcpath,
                        close(labelfd);
                        if (ret <= 0) {
                                SYSERROR("%d", (int)ret);
-                               goto on_error;
+                               goto close_mainloop;
                        }
                        TRACE("Sent LSM label file descriptor %d to child", labelfd);
                }
 
-               /* Now shut down communication with child, we're done. */
-               shutdown(ipc_sockets[0], SHUT_RDWR);
-               close(ipc_sockets[0]);
-               lxc_proc_put_context_info(init_ctx);
-
                /* We're done, the child process should now execute whatever it
                 * is that the user requested. The parent can now track it with
                 * waitpid() or similar.
                 */
 
                *attached_process = attached_pid;
-               return 0;
 
-       on_error:
-               /* First shut down the socket, then wait for the pid, otherwise
-                * the pid we're waiting for may never exit.
-                */
+               /* Now shut down communication with child, we're done. */
                shutdown(ipc_sockets[0], SHUT_RDWR);
                close(ipc_sockets[0]);
-               if (to_cleanup_pid)
+               ipc_sockets[0] = -1;
+
+               ret_parent = 0;
+               to_cleanup_pid = -1;
+               if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
+                       ret = lxc_mainloop(&descr, -1);
+                       if (ret < 0) {
+                               ret_parent = -1;
+                               to_cleanup_pid = attached_pid;
+                       }
+               }
+
+       close_mainloop:
+               if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY)
+                       lxc_mainloop_close(&descr);
+
+       on_error:
+               if (ipc_sockets[0] >= 0) {
+                       shutdown(ipc_sockets[0], SHUT_RDWR);
+                       close(ipc_sockets[0]);
+               }
+
+               if (to_cleanup_pid > 0)
                        (void)wait_for_pid(to_cleanup_pid);
+
+               if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
+                       lxc_console_delete(&pty);
+                       lxc_pty_conf_free(&pty);
+               }
                lxc_proc_put_context_info(init_ctx);
-               return -1;
+               return ret_parent;
        }
 
-       /* First subprocess begins here, we close the socket that is for the
-        * initial thread.
-        */
+       /* close unneeded file descriptors */
        close(ipc_sockets[0]);
+       ipc_sockets[0] = -EBADF;
+       if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY) {
+               lxc_attach_pty_close_master(&pty);
+               lxc_attach_pty_close_peer(&pty);
+               lxc_attach_pty_close_log(&pty);
+       }
 
        /* Wait for the parent to have setup cgroups. */
-       expected = 0;
        ret = lxc_read_nointr(ipc_sockets[1], &status, sizeof(status));
-       if (ret != sizeof(status) || status != expected) {
+       if (ret != sizeof(status)) {
                shutdown(ipc_sockets[1], SHUT_RDWR);
                lxc_proc_put_context_info(init_ctx);
                rexit(-1);
@@ -1351,6 +1505,7 @@ int lxc_attach(const char *name, const char *lxcpath,
        payload.ipc_socket = ipc_sockets[1];
        payload.options = options;
        payload.init_ctx = init_ctx;
+       payload.pty_fd = pty.slave;
        payload.exec_function = exec_function;
        payload.exec_payload = exec_payload;
 
@@ -1368,6 +1523,8 @@ int lxc_attach(const char *name, const char *lxcpath,
                        ERROR("Failed to exec");
                _exit(EXIT_FAILURE);
        }
+       if (options->attach_flags & LXC_ATTACH_ALLOCATE_PTY)
+               lxc_attach_pty_close_slave(&pty);
 
        /* Tell grandparent the pid of the pid of the newly created child. */
        ret = lxc_write_nointr(ipc_sockets[1], &pid, sizeof(pid));
index fad6456ccc4bb79631b7515b2bb4c46b192de7f4..1e64e4abfa363aad1a99c61647e0619641d35b37 100644 (file)
@@ -51,6 +51,7 @@ enum {
        LXC_ATTACH_LSM_NOW               = 0x00020000, /*!< FIXME: unknown */
        /* Set PR_SET_NO_NEW_PRIVS to block execve() gainable privileges. */
        LXC_ATTACH_NO_NEW_PRIVS          = 0x00040000, /*!< PR_SET_NO_NEW_PRIVS */
+       LXC_ATTACH_ALLOCATE_PTY          = 0x00080000, /*!< Allocate new pty for attached process. */
 
        /* We have 16 bits for things that are on by default and 16 bits that
         * are off by default, that should be sufficient to keep binary
index 0615cc719a9fc14479e80a208222999d79f8d9d6..926bf079eea8d9f9761d21e4f2b3ab1a756c4016 100644 (file)
 #include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
 #include <sys/ioctl.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#include <termios.h>
-#include <unistd.h>
 
 #include <lxc/lxccontainer.h>
 
 #include "mainloop.h"
 #include "utils.h"
 
-#if HAVE_PTY_H
-#include <pty.h>
-#else
-#include <../include/openpty.h>
-#endif
-
 static const struct option my_longopts[] = {
        {"elevated-privileges", optional_argument, 0, 'e'},
        {"arch", required_argument, 0, 'a'},
@@ -241,155 +236,29 @@ Options :\n\
        .checker  = NULL,
 };
 
-struct wrapargs {
-       lxc_attach_options_t *options;
-       lxc_attach_command_t *command;
-       struct lxc_console *console;
-       int ptyfd;
-};
-
-/* Minimalistic login_tty() implementation. */
-static int login_pty(int fd)
-{
-       setsid();
-       if (ioctl(fd, TIOCSCTTY, NULL) < 0)
-               return -1;
-       if (lxc_console_set_stdfds(fd) < 0)
-               return -1;
-       if (fd > STDERR_FILENO)
-               close(fd);
-       return 0;
-}
-
-static int get_pty_on_host_callback(void *p)
+static bool stdfd_is_pty(void)
 {
-       struct wrapargs *wrap = p;
-
-       close(wrap->console->master);
-       if (login_pty(wrap->console->slave) < 0)
-               return -1;
+       if (isatty(STDIN_FILENO))
+               return true;
+       if (isatty(STDOUT_FILENO))
+               return true;
+       if (isatty(STDERR_FILENO))
+               return true;
 
-       if (wrap->command->program)
-               lxc_attach_run_command(wrap->command);
-       else
-               lxc_attach_run_shell(NULL);
-       return -1;
+       return false;
 }
 
-static int get_pty_on_host(struct lxc_container *c, struct wrapargs *wrap, int *pid)
+int lxc_attach_create_log_file(const char *log_file)
 {
-       struct lxc_epoll_descr descr;
-       struct lxc_conf *conf;
-       struct lxc_tty_state *ts;
-       int ret = -1;
-       struct wrapargs *args = wrap;
-
-       if (!isatty(args->ptyfd)) {
-               fprintf(stderr, "Standard file descriptor does not refer to a pty\n");
-               return -1;
-       }
-
-       if (c->lxc_conf) {
-               conf = c->lxc_conf;
-       } else {
-               /* If the container is not defined and the user didn't specify a
-                * config file to load we will simply init a dummy config here.
-                */
-               conf = lxc_conf_init();
-               if (!conf) {
-                       fprintf(stderr, "Failed to allocate dummy config file for the container\n");
-                       return -1;
-               }
+       int fd;
 
-               /* We also need a dummy rootfs path otherwise
-                * lxc_console_create() will not let us create a console. Note,
-                * I don't want this change to make it into
-                * lxc_console_create()'s since this function will only be
-                * responsible for proper /dev/{console,tty<n>} devices.
-                * lxc-attach is just abusing it to also handle the pty case
-                * because it is very similar. However, with LXC 3.0 lxc-attach
-                * will need to move away from using lxc_console_create() since
-                * this is actually an internal symbol and we only want the
-                * tools to use the API with LXC 3.0.
-                */
-               conf->rootfs.path = strdup("dummy");
-               if (!conf->rootfs.path)
-                       return -1;
-       }
-       free(conf->console.log_path);
-       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
-        * lxc.console.path here and set it NULL. lxc_console_peer_default()
-        * will then try to open /dev/tty. If the process doesn't have a
-        * controlling terminal we should still proceed.
-        */
-       free(conf->console.path);
-       conf->console.path = NULL;
-
-       /* Create pty on the host. */
-       if (lxc_console_create(conf) < 0)
+       fd = open(log_file, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600);
+       if (fd < 0) {
+               fprintf(stderr, "Failed to open log file \"%s\"\n", log_file);
                return -1;
-       ts = conf->console.tty_state;
-       conf->console.descr = &descr;
-
-       /* Shift ttys to container. */
-       ret = lxc_pty_map_ids(conf, &conf->console);
-       if (ret < 0) {
-               fprintf(stderr, "Failed to shift tty into container\n");
-               goto err1;
-       }
-
-       /* Send wrapper function on its way. */
-       wrap->console = &conf->console;
-       if (c->attach(c, get_pty_on_host_callback, wrap, wrap->options, pid) < 0)
-               goto err1;
-       close(conf->console.slave); /* Close slave side. */
-       conf->console.slave = -1;
-
-       ret = lxc_mainloop_open(&descr);
-       if (ret) {
-               fprintf(stderr, "failed to create mainloop\n");
-               goto err2;
        }
 
-       if (lxc_console_mainloop_add(&descr, &conf->console) < 0) {
-               fprintf(stderr, "Failed to add handlers to lxc mainloop.\n");
-               goto err3;
-       }
-
-       ret = lxc_mainloop(&descr, -1);
-       if (ret) {
-               fprintf(stderr, "mainloop returned an error\n");
-               goto err3;
-       }
-       ret = 0;
-
-err3:
-       lxc_mainloop_close(&descr);
-err2:
-       if (ts && ts->sigfd != -1)
-               lxc_console_signal_fini(ts);
-err1:
-       lxc_console_delete(&conf->console);
-
-       return ret;
-}
-
-static int stdfd_is_pty(void)
-{
-       if (isatty(STDIN_FILENO))
-               return STDIN_FILENO;
-       if (isatty(STDOUT_FILENO))
-               return STDOUT_FILENO;
-       if (isatty(STDERR_FILENO))
-               return STDERR_FILENO;
-
-       return -1;
+       return fd;
 }
 
 int main(int argc, char *argv[])
@@ -463,6 +332,8 @@ int main(int argc, char *argv[])
                attach_options.attach_flags |= LXC_ATTACH_REMOUNT_PROC_SYS;
        if (elevated_privileges)
                attach_options.attach_flags &= ~(elevated_privileges);
+       if (stdfd_is_pty())
+               attach_options.attach_flags |= LXC_ATTACH_ALLOCATE_PTY;
        attach_options.namespaces = namespace_flags;
        attach_options.personality = new_personality;
        attach_options.env_policy = env_policy;
@@ -474,29 +345,17 @@ int main(int argc, char *argv[])
                command.argv = (char**)my_args.argv;
        }
 
-       struct wrapargs wrap = (struct wrapargs){
-               .command = &command,
-               .options = &attach_options
-       };
-
-       wrap.ptyfd = stdfd_is_pty();
-       if (wrap.ptyfd >= 0) {
-               if ((!isatty(STDOUT_FILENO) || !isatty(STDERR_FILENO)) && my_args.console_log) {
-                       fprintf(stderr, "-L/--pty-log can only be used when stdout and stderr refer to a pty.\n");
-                       goto out;
-               }
-               ret = get_pty_on_host(c, &wrap, &pid);
-       } else {
-               if (my_args.console_log) {
-                       fprintf(stderr, "-L/--pty-log can only be used when stdout and stderr refer to a pty.\n");
+       if (my_args.console_log) {
+               attach_options.log_fd = lxc_attach_create_log_file(my_args.console_log);
+               if (attach_options.log_fd < 0)
                        goto out;
-               }
-               if (command.program)
-                       ret = c->attach(c, lxc_attach_run_command, &command, &attach_options, &pid);
-               else
-                       ret = c->attach(c, lxc_attach_run_shell, NULL, &attach_options, &pid);
        }
 
+       if (command.program)
+               ret = c->attach(c, lxc_attach_run_command, &command, &attach_options, &pid);
+       else
+               ret = c->attach(c, lxc_attach_run_shell, NULL, &attach_options, &pid);
+
        if (ret < 0)
                goto out;
 
index 7bf5ef17969d27be5efb674dba90df16589adec7..2c771278c44341ed6a73ac69312cffbe08d174a4 100644 (file)
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#include <lxc/lxccontainer.h>
-#include "lxc/utils.h"
-#include "lxc/lsm/lsm.h"
-
-#include <sys/types.h>
+#include <errno.h>
 #include <string.h>
 #include <unistd.h>
 #include <sys/stat.h>
 #include <sys/syscall.h>
-#include <errno.h>
+#include <sys/types.h>
+
+#include "lxctest.h"
+#include "utils.h"
+#include "lsm/lsm.h"
+
+#include <lxc/lxccontainer.h>
 
 #define TSTNAME    "lxc-attach-test"
 #define TSTOUT(fmt, ...) do { \
@@ -392,19 +394,60 @@ err1:
 
 int main(int argc, char *argv[])
 {
-       int ret;
+       int i, ret;
+       struct lxc_log log;
+       char template[sizeof(P_tmpdir"/attach_XXXXXX")];
+       int fret = EXIT_FAILURE;
+
+       strcpy(template, P_tmpdir"/attach_XXXXXX");
+       i = lxc_make_tmpfile(template, false);
+       if (i < 0) {
+               lxc_error("Failed to create temporary log file for container %s\n", TSTNAME);
+               exit(EXIT_FAILURE);
+       } else {
+               lxc_debug("Using \"%s\" as temporary log file for container %s\n", template, TSTNAME);
+               close(i);
+       }
+
+       log.name = TSTNAME;
+       log.file = template;
+       log.level = "TRACE";
+       log.prefix = "attach";
+       log.quiet = false;
+       log.lxcpath = NULL;
+       if (lxc_log_init(&log))
+               goto on_error;
 
        test_lsm_detect();
        ret = test_attach(NULL, TSTNAME, "busybox");
        if (ret < 0)
-               return EXIT_FAILURE;
+               goto on_error;
 
        TSTOUT("\n");
        ret = test_attach(LXCPATH "/alternate-path-test", TSTNAME, "busybox");
        if (ret < 0)
-               return EXIT_FAILURE;
+               goto on_error;
 
-       (void)rmdir(LXCPATH "/alternate-path-test");
        TSTOUT("All tests passed\n");
-       return EXIT_SUCCESS;
+       fret = EXIT_SUCCESS;
+
+on_error:
+       if (fret != EXIT_SUCCESS) {
+               int fd;
+
+               fd = open(template, O_RDONLY);
+               if (fd >= 0) {
+                       char buf[4096];
+                       ssize_t buflen;
+                       while ((buflen = read(fd, buf, 1024)) > 0) {
+                               buflen = write(STDERR_FILENO, buf, buflen);
+                               if (buflen <= 0)
+                                       break;
+                       }
+                       close(fd);
+               }
+       }
+       (void)rmdir(LXCPATH "/alternate-path-test");
+       (void)unlink(template);
+       exit(fret);
 }
index 380a6db305b8c739177f793105d3a0885740c24c..2aa0b830bb5a03f014319ae841099ad23e623bf4 100755 (executable)
@@ -190,17 +190,6 @@ fi
 
 rm -f $out $err
 
-if [ $allocate_pty = "pty" ]; then
-       # Test whether logging pty output to a file works.
-       trap "rm -f /tmp/ptylog" EXIT INT QUIT PIPE
-       lxc-attach -n busy -L /tmp/ptylog -- hostname || FAIL "to allocate or setup pty"
-       if [ ! -s /tmp/ptylog ]; then
-               FAIL "lxc-attach -n busy -L /tmp/ptylog -- hostname"
-       fi
-
-       rm -f /tmp/ptylog
-fi
-
 lxc-destroy -n busy -f
 
 exit 0