mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-07-29 17:46:46 +00:00
Merge pull request #839 from brauner/2016-02-15/lxc_attach_pty
lxc-attach: add comment, & implement login_tty()
This commit is contained in:
commit
b5c8400909
@ -210,6 +210,19 @@ struct wrapargs {
|
|||||||
int ptyfd;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/* Minimalistic forkpty() implementation. */
|
/* Minimalistic forkpty() implementation. */
|
||||||
static pid_t fork_pty(int *masterfd)
|
static pid_t fork_pty(int *masterfd)
|
||||||
{
|
{
|
||||||
@ -226,11 +239,8 @@ static pid_t fork_pty(int *masterfd)
|
|||||||
return -1;
|
return -1;
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
close(master);
|
close(master);
|
||||||
setsid();
|
if (login_pty(slave) < 0)
|
||||||
if (ioctl(slave, TIOCSCTTY, NULL) < 0)
|
_exit(-1); /* closes fds */
|
||||||
_exit(-1); /* automatically closes fds */
|
|
||||||
if (lxc_console_set_stdfds(slave) < 0)
|
|
||||||
_exit(-1); /* automatically closes fds */
|
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
*masterfd = master;
|
*masterfd = master;
|
||||||
@ -239,6 +249,29 @@ static pid_t fork_pty(int *masterfd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is probably redundant but just so that intentions can be checked against
|
||||||
|
* code for future modifications. Here is what this is supposed to achieve:
|
||||||
|
* Since we fork() in pty_in_container() the shell that is run on the slave side
|
||||||
|
* of the pty is the grandchild of c->attach() in main(). But what we probably
|
||||||
|
* are interested in is the exit code of the grandchild. So we wait for the
|
||||||
|
* grandchild to change status and return its exit code from this function. We
|
||||||
|
* thereby make the exit code of the grandchild the exit code of the child and
|
||||||
|
* allow the grandparent to see the exit code of the grandchild by waiting on
|
||||||
|
* the pid of the child to change status:
|
||||||
|
*
|
||||||
|
* grandchild: lxc_attach_run_command()/lxc_attach_run_shell()
|
||||||
|
*
|
||||||
|
* child: pty_in_container()
|
||||||
|
* - perform waitpid() on pid returned by lxc_attach_run_command() or
|
||||||
|
* lxc_attach_run_shell()
|
||||||
|
*
|
||||||
|
* grandparent: c->attach()
|
||||||
|
* - return pid of pty_in_container() in pid argument.
|
||||||
|
*
|
||||||
|
* main()
|
||||||
|
* - perform waitpid() on pid returned in pid argument of c->attach()
|
||||||
|
*/
|
||||||
static int pty_in_container(void *p)
|
static int pty_in_container(void *p)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -335,9 +368,14 @@ err2:
|
|||||||
err1:
|
err1:
|
||||||
tcsetattr(args->ptyfd, TCSAFLUSH, &oldtios);
|
tcsetattr(args->ptyfd, TCSAFLUSH, &oldtios);
|
||||||
|
|
||||||
if (pid > 0)
|
ret = lxc_wait_for_pid_status(pid);
|
||||||
ret = lxc_wait_for_pid_status(pid);
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (WIFEXITED(ret))
|
||||||
|
return WEXITSTATUS(ret);
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pty_on_host_callback(void *p)
|
static int pty_on_host_callback(void *p)
|
||||||
@ -345,16 +383,13 @@ static int pty_on_host_callback(void *p)
|
|||||||
struct wrapargs *wrap = p;
|
struct wrapargs *wrap = p;
|
||||||
|
|
||||||
close(wrap->console->master);
|
close(wrap->console->master);
|
||||||
setsid();
|
if (login_pty(wrap->console->slave) < 0)
|
||||||
ioctl(wrap->console->slave, TIOCSCTTY, NULL);
|
|
||||||
if (lxc_console_set_stdfds(wrap->console->slave) < 0)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (wrap->command->program)
|
if (wrap->command->program)
|
||||||
lxc_attach_run_command(wrap->command);
|
lxc_attach_run_command(wrap->command);
|
||||||
else
|
else
|
||||||
lxc_attach_run_shell(NULL);
|
lxc_attach_run_shell(NULL);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,7 +500,7 @@ int main(int argc, char *argv[])
|
|||||||
if (access(my_args.lxcpath[0], O_RDWR) < 0) {
|
if (access(my_args.lxcpath[0], O_RDWR) < 0) {
|
||||||
if (!my_args.quiet)
|
if (!my_args.quiet)
|
||||||
fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
|
fprintf(stderr, "You lack access to %s\n", my_args.lxcpath[0]);
|
||||||
exit(ret);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user