Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
L
lxc
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Chen Yisong
lxc
Commits
cee1de17
Commit
cee1de17
authored
Feb 21, 2016
by
Serge Hallyn
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #825 from brauner/2016-02-15/lxc_attach_pty
make lxc-attach use a pty
parents
0b095804
5eacdc3d
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
412 additions
and
87 deletions
+412
-87
cgmanager.c
src/lxc/cgmanager.c
+2
-2
console.c
src/lxc/console.c
+72
-66
console.h
src/lxc/console.h
+27
-1
lxc_attach.c
src/lxc/lxc_attach.c
+310
-17
start.c
src/lxc/start.c
+1
-1
No files found.
src/lxc/cgmanager.c
View file @
cee1de17
...
@@ -1332,7 +1332,7 @@ out:
...
@@ -1332,7 +1332,7 @@ out:
return
bret
;
return
bret
;
}
}
static
bool
collect_subsytems
(
void
)
static
bool
collect_subsy
s
tems
(
void
)
{
{
char
*
line
=
NULL
;
char
*
line
=
NULL
;
nih_local
char
**
cgm_subsys_list
=
NULL
;
nih_local
char
**
cgm_subsys_list
=
NULL
;
...
@@ -1444,7 +1444,7 @@ out_free:
...
@@ -1444,7 +1444,7 @@ out_free:
struct
cgroup_ops
*
cgm_ops_init
(
void
)
struct
cgroup_ops
*
cgm_ops_init
(
void
)
{
{
check_supports_multiple_controllers
(
-
1
);
check_supports_multiple_controllers
(
-
1
);
if
(
!
collect_subsytems
())
if
(
!
collect_subsy
s
tems
())
return
NULL
;
return
NULL
;
if
(
api_version
<
CGM_SUPPORTS_MULT_CONTROLLERS
)
if
(
api_version
<
CGM_SUPPORTS_MULT_CONTROLLERS
)
...
...
src/lxc/console.c
View file @
cee1de17
...
@@ -22,26 +22,28 @@
...
@@ -22,26 +22,28 @@
*/
*/
#include <assert.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <signal.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/types.h>
#include <termios.h>
#include <termios.h>
#include <unistd.h>
#include <lxc/lxccontainer.h>
#include <lxc/lxccontainer.h>
#include "log.h"
#include "af_unix.h"
#include "conf.h"
#include "config.h"
#include "start.h"
/* for struct lxc_handler */
#include "caps.h"
#include "caps.h"
#include "commands.h"
#include "commands.h"
#include "mainloop.h"
#include "conf.h"
#include "af_unix.h"
#include "config.h"
#include "console.h"
#include "log.h"
#include "lxclock.h"
#include "lxclock.h"
#include "mainloop.h"
#include "start.h"
/* for struct lxc_handler */
#include "utils.h"
#include "utils.h"
#if HAVE_PTY_H
#if HAVE_PTY_H
...
@@ -55,19 +57,6 @@ lxc_log_define(lxc_console, lxc);
...
@@ -55,19 +57,6 @@ lxc_log_define(lxc_console, lxc);
static
struct
lxc_list
lxc_ttys
;
static
struct
lxc_list
lxc_ttys
;
typedef
void
(
*
sighandler_t
)(
int
);
typedef
void
(
*
sighandler_t
)(
int
);
struct
lxc_tty_state
{
struct
lxc_list
node
;
int
stdinfd
;
int
stdoutfd
;
int
masterfd
;
int
escape
;
int
saw_escape
;
const
char
*
winch_proxy
;
const
char
*
winch_proxy_lxcpath
;
int
sigfd
;
sigset_t
oldmask
;
};
__attribute__
((
constructor
))
__attribute__
((
constructor
))
void
lxc_console_init
(
void
)
void
lxc_console_init
(
void
)
...
@@ -80,7 +69,7 @@ void lxc_console_init(void)
...
@@ -80,7 +69,7 @@ void lxc_console_init(void)
* @srcfd : terminal to get size from (typically a slave pty)
* @srcfd : terminal to get size from (typically a slave pty)
* @dstfd : terminal to set size on (typically a master pty)
* @dstfd : terminal to set size on (typically a master pty)
*/
*/
static
void
lxc_console_winsz
(
int
srcfd
,
int
dstfd
)
void
lxc_console_winsz
(
int
srcfd
,
int
dstfd
)
{
{
struct
winsize
wsz
;
struct
winsize
wsz
;
if
(
isatty
(
srcfd
)
&&
ioctl
(
srcfd
,
TIOCGWINSZ
,
&
wsz
)
==
0
)
{
if
(
isatty
(
srcfd
)
&&
ioctl
(
srcfd
,
TIOCGWINSZ
,
&
wsz
)
==
0
)
{
...
@@ -93,10 +82,8 @@ static void lxc_console_winsz(int srcfd, int dstfd)
...
@@ -93,10 +82,8 @@ static void lxc_console_winsz(int srcfd, int dstfd)
static
void
lxc_console_winch
(
struct
lxc_tty_state
*
ts
)
static
void
lxc_console_winch
(
struct
lxc_tty_state
*
ts
)
{
{
lxc_console_winsz
(
ts
->
stdinfd
,
ts
->
masterfd
);
lxc_console_winsz
(
ts
->
stdinfd
,
ts
->
masterfd
);
if
(
ts
->
winch_proxy
)
{
if
(
ts
->
winch_proxy
)
lxc_cmd_console_winch
(
ts
->
winch_proxy
,
lxc_cmd_console_winch
(
ts
->
winch_proxy
,
ts
->
winch_proxy_lxcpath
);
ts
->
winch_proxy_lxcpath
);
}
}
}
void
lxc_console_sigwinch
(
int
sig
)
void
lxc_console_sigwinch
(
int
sig
)
...
@@ -110,13 +97,14 @@ void lxc_console_sigwinch(int sig)
...
@@ -110,13 +97,14 @@ void lxc_console_sigwinch(int sig)
}
}
}
}
static
int
lxc_console_cb_sigwinch_fd
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
int
lxc_console_cb_sigwinch_fd
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
)
struct
lxc_epoll_descr
*
descr
)
{
{
struct
signalfd_siginfo
siginfo
;
struct
signalfd_siginfo
siginfo
;
struct
lxc_tty_state
*
ts
=
cbdata
;
struct
lxc_tty_state
*
ts
=
cbdata
;
if
(
read
(
fd
,
&
siginfo
,
sizeof
(
siginfo
))
<
sizeof
(
siginfo
))
{
ssize_t
ret
=
read
(
fd
,
&
siginfo
,
sizeof
(
siginfo
));
if
(
ret
<
0
||
(
size_t
)
ret
<
sizeof
(
siginfo
))
{
ERROR
(
"failed to read signal info"
);
ERROR
(
"failed to read signal info"
);
return
-
1
;
return
-
1
;
}
}
...
@@ -145,7 +133,7 @@ static int lxc_console_cb_sigwinch_fd(int fd, uint32_t events, void *cbdata,
...
@@ -145,7 +133,7 @@ static int lxc_console_cb_sigwinch_fd(int fd, uint32_t events, void *cbdata,
* prevent lxc_ttys list corruption, but using the fd we can provide the
* prevent lxc_ttys list corruption, but using the fd we can provide the
* tty_state needed to the callback (lxc_console_cb_sigwinch_fd()).
* tty_state needed to the callback (lxc_console_cb_sigwinch_fd()).
*/
*/
st
atic
st
ruct
lxc_tty_state
*
lxc_console_sigwinch_init
(
int
srcfd
,
int
dstfd
)
struct
lxc_tty_state
*
lxc_console_sigwinch_init
(
int
srcfd
,
int
dstfd
)
{
{
sigset_t
mask
;
sigset_t
mask
;
struct
lxc_tty_state
*
ts
;
struct
lxc_tty_state
*
ts
;
...
@@ -200,11 +188,11 @@ out:
...
@@ -200,11 +188,11 @@ out:
* Must be called with process_lock held to protect the lxc_ttys list, or
* Must be called with process_lock held to protect the lxc_ttys list, or
* from a non-threaded context.
* from a non-threaded context.
*/
*/
static
void
lxc_console_sigwinch_fini
(
struct
lxc_tty_state
*
ts
)
void
lxc_console_sigwinch_fini
(
struct
lxc_tty_state
*
ts
)
{
{
if
(
ts
->
sigfd
>=
0
)
{
if
(
ts
->
sigfd
>=
0
)
close
(
ts
->
sigfd
);
close
(
ts
->
sigfd
);
}
lxc_list_del
(
&
ts
->
node
);
lxc_list_del
(
&
ts
->
node
);
sigprocmask
(
SIG_SETMASK
,
&
ts
->
oldmask
,
NULL
);
sigprocmask
(
SIG_SETMASK
,
&
ts
->
oldmask
,
NULL
);
free
(
ts
);
free
(
ts
);
...
@@ -243,6 +231,7 @@ static int lxc_console_cb_con(int fd, uint32_t events, void *data,
...
@@ -243,6 +231,7 @@ static int lxc_console_cb_con(int fd, uint32_t events, void *data,
if
(
w
!=
r
)
if
(
w
!=
r
)
WARN
(
"console short write r:%d w:%d"
,
r
,
w
);
WARN
(
"console short write r:%d w:%d"
,
r
,
w
);
return
0
;
return
0
;
}
}
...
@@ -302,7 +291,7 @@ int lxc_console_mainloop_add(struct lxc_epoll_descr *descr,
...
@@ -302,7 +291,7 @@ int lxc_console_mainloop_add(struct lxc_epoll_descr *descr,
return
0
;
return
0
;
}
}
static
int
setup_tios
(
int
fd
,
struct
termios
*
oldtios
)
int
lxc_
setup_tios
(
int
fd
,
struct
termios
*
oldtios
)
{
{
struct
termios
newtios
;
struct
termios
newtios
;
...
@@ -382,7 +371,7 @@ static int lxc_console_peer_proxy_alloc(struct lxc_console *console, int sockfd)
...
@@ -382,7 +371,7 @@ static int lxc_console_peer_proxy_alloc(struct lxc_console *console, int sockfd)
return
-
1
;
return
-
1
;
}
}
if
(
setup_tios
(
console
->
peerpty
.
slave
,
&
oldtermio
)
<
0
)
if
(
lxc_
setup_tios
(
console
->
peerpty
.
slave
,
&
oldtermio
)
<
0
)
goto
err1
;
goto
err1
;
ts
=
lxc_console_sigwinch_init
(
console
->
peerpty
.
master
,
console
->
master
);
ts
=
lxc_console_sigwinch_init
(
console
->
peerpty
.
master
,
console
->
master
);
...
@@ -435,9 +424,8 @@ int lxc_console_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
...
@@ -435,9 +424,8 @@ int lxc_console_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
}
}
/* search for next available tty, fixup index tty1 => [0] */
/* search for next available tty, fixup index tty1 => [0] */
for
(
ttynum
=
1
;
for
(
ttynum
=
1
;
ttynum
<=
tty_info
->
nbtty
&&
tty_info
->
pty_info
[
ttynum
-
1
].
busy
;
ttynum
++
)
ttynum
<=
tty_info
->
nbtty
&&
tty_info
->
pty_info
[
ttynum
-
1
].
busy
;
;
ttynum
++
);
/* we didn't find any available slot for tty */
/* we didn't find any available slot for tty */
if
(
ttynum
>
tty_info
->
nbtty
)
if
(
ttynum
>
tty_info
->
nbtty
)
...
@@ -521,7 +509,7 @@ static void lxc_console_peer_default(struct lxc_console *console)
...
@@ -521,7 +509,7 @@ static void lxc_console_peer_default(struct lxc_console *console)
goto
err1
;
goto
err1
;
}
}
if
(
setup_tios
(
console
->
peer
,
console
->
tios
)
<
0
)
if
(
lxc_
setup_tios
(
console
->
peer
,
console
->
tios
)
<
0
)
goto
err2
;
goto
err2
;
return
;
return
;
...
@@ -611,46 +599,60 @@ err:
...
@@ -611,46 +599,60 @@ err:
return
-
1
;
return
-
1
;
}
}
int
lxc_console_set_stdfds
(
struct
lxc_handler
*
handler
)
int
lxc_console_set_stdfds
(
int
fd
)
{
{
struct
lxc_conf
*
conf
=
handler
->
conf
;
if
(
fd
<
0
)
struct
lxc_console
*
console
=
&
conf
->
console
;
if
(
console
->
slave
<
0
)
return
0
;
return
0
;
if
(
dup2
(
console
->
slave
,
0
)
<
0
||
if
(
isatty
(
STDIN_FILENO
))
dup2
(
console
->
slave
,
1
)
<
0
||
if
(
dup2
(
fd
,
STDIN_FILENO
)
<
0
)
{
dup2
(
console
->
slave
,
2
)
<
0
)
SYSERROR
(
"failed to duplicate stdin."
);
{
return
-
1
;
SYSERROR
(
"failed to dup console"
);
}
return
-
1
;
}
if
(
isatty
(
STDOUT_FILENO
))
if
(
dup2
(
fd
,
STDOUT_FILENO
)
<
0
)
{
SYSERROR
(
"failed to duplicate stdout."
);
return
-
1
;
}
if
(
isatty
(
STDERR_FILENO
))
if
(
dup2
(
fd
,
STDERR_FILENO
)
<
0
)
{
SYSERROR
(
"failed to duplicate stderr."
);
return
-
1
;
}
return
0
;
return
0
;
}
}
static
int
lxc_console_cb_tty_stdin
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
int
lxc_console_cb_tty_stdin
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
)
struct
lxc_epoll_descr
*
descr
)
{
{
struct
lxc_tty_state
*
ts
=
cbdata
;
struct
lxc_tty_state
*
ts
=
cbdata
;
char
c
;
char
c
;
if
(
events
&
EPOLLHUP
)
return
1
;
assert
(
fd
==
ts
->
stdinfd
);
assert
(
fd
==
ts
->
stdinfd
);
if
(
read
(
ts
->
stdinfd
,
&
c
,
1
)
<
0
)
{
if
(
read
(
ts
->
stdinfd
,
&
c
,
1
)
<
0
)
{
SYSERROR
(
"failed to read"
);
SYSERROR
(
"failed to read"
);
return
1
;
return
1
;
}
}
/* we want to exit the console with Ctrl+a q */
if
(
ts
->
escape
!=
-
1
)
{
if
(
c
==
ts
->
escape
&&
!
ts
->
saw_escape
)
{
/* we want to exit the console with Ctrl+a q */
ts
->
saw_escape
=
1
;
if
(
c
==
ts
->
escape
&&
!
ts
->
saw_escape
)
{
return
0
;
ts
->
saw_escape
=
1
;
}
return
0
;
}
if
(
c
==
'q'
&&
ts
->
saw_escape
)
if
(
c
==
'q'
&&
ts
->
saw_escape
)
return
1
;
return
1
;
ts
->
saw_escape
=
0
;
}
ts
->
saw_escape
=
0
;
if
(
write
(
ts
->
masterfd
,
&
c
,
1
)
<
0
)
{
if
(
write
(
ts
->
masterfd
,
&
c
,
1
)
<
0
)
{
SYSERROR
(
"failed to write"
);
SYSERROR
(
"failed to write"
);
return
1
;
return
1
;
...
@@ -659,12 +661,15 @@ static int lxc_console_cb_tty_stdin(int fd, uint32_t events, void *cbdata,
...
@@ -659,12 +661,15 @@ static int lxc_console_cb_tty_stdin(int fd, uint32_t events, void *cbdata,
return
0
;
return
0
;
}
}
static
int
lxc_console_cb_tty_master
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
int
lxc_console_cb_tty_master
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
)
struct
lxc_epoll_descr
*
descr
)
{
{
struct
lxc_tty_state
*
ts
=
cbdata
;
struct
lxc_tty_state
*
ts
=
cbdata
;
char
buf
[
1024
];
char
buf
[
1024
];
int
r
,
w
;
int
r
,
w
;
if
(
events
&
EPOLLHUP
)
return
1
;
assert
(
fd
==
ts
->
masterfd
);
assert
(
fd
==
ts
->
masterfd
);
r
=
read
(
fd
,
buf
,
sizeof
(
buf
));
r
=
read
(
fd
,
buf
,
sizeof
(
buf
));
...
@@ -701,7 +706,7 @@ int lxc_console(struct lxc_container *c, int ttynum,
...
@@ -701,7 +706,7 @@ int lxc_console(struct lxc_container *c, int ttynum,
return
-
1
;
return
-
1
;
}
}
ret
=
setup_tios
(
stdinfd
,
&
oldtios
);
ret
=
lxc_
setup_tios
(
stdinfd
,
&
oldtios
);
if
(
ret
)
{
if
(
ret
)
{
ERROR
(
"failed to setup tios"
);
ERROR
(
"failed to setup tios"
);
return
-
1
;
return
-
1
;
...
@@ -782,3 +787,4 @@ err1:
...
@@ -782,3 +787,4 @@ err1:
return
ret
;
return
ret
;
}
}
src/lxc/console.h
View file @
cee1de17
...
@@ -24,8 +24,24 @@
...
@@ -24,8 +24,24 @@
#ifndef __LXC_CONSOLE_H
#ifndef __LXC_CONSOLE_H
#define __LXC_CONSOLE_H
#define __LXC_CONSOLE_H
#include "conf.h"
#include "list.h"
struct
lxc_epoll_descr
;
struct
lxc_epoll_descr
;
struct
lxc_container
;
struct
lxc_container
;
struct
lxc_tty_state
{
struct
lxc_list
node
;
int
stdinfd
;
int
stdoutfd
;
int
masterfd
;
int
escape
;
int
saw_escape
;
const
char
*
winch_proxy
;
const
char
*
winch_proxy_lxcpath
;
int
sigfd
;
sigset_t
oldmask
;
};
extern
int
lxc_console_allocate
(
struct
lxc_conf
*
conf
,
int
sockfd
,
int
*
ttynum
);
extern
int
lxc_console_allocate
(
struct
lxc_conf
*
conf
,
int
sockfd
,
int
*
ttynum
);
extern
int
lxc_console_create
(
struct
lxc_conf
*
);
extern
int
lxc_console_create
(
struct
lxc_conf
*
);
...
@@ -39,6 +55,16 @@ extern int lxc_console(struct lxc_container *c, int ttynum,
...
@@ -39,6 +55,16 @@ extern int lxc_console(struct lxc_container *c, int ttynum,
int
escape
);
int
escape
);
extern
int
lxc_console_getfd
(
struct
lxc_container
*
c
,
int
*
ttynum
,
extern
int
lxc_console_getfd
(
struct
lxc_container
*
c
,
int
*
ttynum
,
int
*
masterfd
);
int
*
masterfd
);
extern
int
lxc_console_set_stdfds
(
struct
lxc_handler
*
);
extern
int
lxc_console_set_stdfds
(
int
fd
);
extern
int
lxc_console_cb_tty_stdin
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
);
extern
int
lxc_console_cb_tty_master
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
);
extern
int
lxc_setup_tios
(
int
fd
,
struct
termios
*
oldtios
);
extern
void
lxc_console_winsz
(
int
srcfd
,
int
dstfd
);
extern
int
lxc_console_cb_sigwinch_fd
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
);
extern
struct
lxc_tty_state
*
lxc_console_sigwinch_init
(
int
srcfd
,
int
dstfd
);
extern
void
lxc_console_sigwinch_fini
(
struct
lxc_tty_state
*
ts
);
#endif
#endif
src/lxc/lxc_attach.c
View file @
cee1de17
...
@@ -23,19 +23,35 @@
...
@@ -23,19 +23,35 @@
#define _GNU_SOURCE
#define _GNU_SOURCE
#include <assert.h>
#include <assert.h>
#include <sys/wait.h>
#include <errno.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <termios.h>
#include <unistd.h>
#include <lxc/lxccontainer.h>
#include "attach.h"
#include "attach.h"
#include "arguments.h"
#include "arguments.h"
#include "caps.h"
#include "config.h"
#include "config.h"
#include "confile.h"
#include "confile.h"
#include "namespace.h"
#include "console.h"
#include "caps.h"
#include "log.h"
#include "log.h"
#include "list.h"
#include "mainloop.h"
#include "utils.h"
#include "utils.h"
#if HAVE_PTY_H
#include <pty.h>
#else
#include <../include/openpty.h>
#endif
lxc_log_define
(
lxc_attach_ui
,
lxc
);
lxc_log_define
(
lxc_attach_ui
,
lxc
);
static
const
struct
option
my_longopts
[]
=
{
static
const
struct
option
my_longopts
[]
=
{
...
@@ -186,20 +202,255 @@ Options :\n\
...
@@ -186,20 +202,255 @@ Options :\n\
.
checker
=
NULL
,
.
checker
=
NULL
,
};
};
int
main
(
int
argc
,
char
*
argv
[])
struct
wrapargs
{
lxc_attach_options_t
*
options
;
lxc_attach_command_t
*
command
;
struct
lxc_tty_state
*
ts
;
struct
lxc_console
*
console
;
int
ptyfd
;
};
/* Minimalistic forkpty() implementation. */
static
pid_t
fork_pty
(
int
*
masterfd
)
{
int
master
,
slave
;
int
ret
=
openpty
(
&
master
,
&
slave
,
NULL
,
NULL
,
NULL
);
if
(
ret
<
0
)
return
-
1
;
pid_t
pid
=
fork
();
if
(
pid
<
0
)
{
close
(
master
);
close
(
slave
);
return
-
1
;
}
else
if
(
pid
==
0
)
{
close
(
master
);
setsid
();
if
(
ioctl
(
slave
,
TIOCSCTTY
,
NULL
)
<
0
)
_Exit
(
-
1
);
/* automatically closes fds */
if
(
lxc_console_set_stdfds
(
slave
)
<
0
)
_Exit
(
-
1
);
/* automatically closes fds */
return
0
;
}
else
{
*
masterfd
=
master
;
close
(
slave
);
return
pid
;
}
}
static
int
pty_in_container
(
void
*
p
)
{
{
int
ret
;
int
ret
;
int
pid
=
-
1
;
int
master
=
-
1
;
struct
wrapargs
*
args
=
p
;
INFO
(
"Trying to allocate a pty in the container."
);
if
(
!
isatty
(
args
->
ptyfd
))
{
ERROR
(
"stdin is not a tty"
);
return
-
1
;
}
/* Get termios from one of the stdfds. */
struct
termios
oldtios
;
ret
=
lxc_setup_tios
(
args
->
ptyfd
,
&
oldtios
);
if
(
ret
<
0
)
return
-
1
;
/* Create master/slave fd pair for pty. */
pid
=
fork_pty
(
&
master
);
if
(
pid
<
0
)
goto
err1
;
/* Pass windowsize from one of the stdfds to the current masterfd. */
lxc_console_winsz
(
args
->
ptyfd
,
master
);
/* Run shell/command on slave side of pty. */
if
(
pid
==
0
)
{
if
(
args
->
command
->
program
)
lxc_attach_run_command
(
args
->
command
);
else
lxc_attach_run_shell
(
NULL
);
return
-
1
;
}
/*
* For future reference: Must use process_lock() when called from a
* threaded context.
*/
args
->
ts
=
lxc_console_sigwinch_init
(
args
->
ptyfd
,
master
);
if
(
!
args
->
ts
)
{
ret
=
-
1
;
goto
err2
;
}
args
->
ts
->
escape
=
-
1
;
args
->
ts
->
stdoutfd
=
STDOUT_FILENO
;
args
->
ts
->
winch_proxy
=
NULL
;
struct
lxc_epoll_descr
descr
;
ret
=
lxc_mainloop_open
(
&
descr
);
if
(
ret
)
{
ERROR
(
"failed to create mainloop"
);
goto
err3
;
}
/* Register sigwinch handler in mainloop. */
ret
=
lxc_mainloop_add_handler
(
&
descr
,
args
->
ts
->
sigfd
,
lxc_console_cb_sigwinch_fd
,
args
->
ts
);
if
(
ret
)
{
ERROR
(
"failed to add handler for SIGWINCH fd"
);
goto
err4
;
}
/* Register i/o callbacks in mainloop. */
ret
=
lxc_mainloop_add_handler
(
&
descr
,
args
->
ts
->
stdinfd
,
lxc_console_cb_tty_stdin
,
args
->
ts
);
if
(
ret
)
{
ERROR
(
"failed to add handler for stdinfd"
);
goto
err4
;
}
ret
=
lxc_mainloop_add_handler
(
&
descr
,
args
->
ts
->
masterfd
,
lxc_console_cb_tty_master
,
args
->
ts
);
if
(
ret
)
{
ERROR
(
"failed to add handler for masterfd"
);
goto
err4
;
}
ret
=
lxc_mainloop
(
&
descr
,
-
1
);
if
(
ret
)
{
ERROR
(
"mainloop returned an error"
);
goto
err4
;
}
err4:
lxc_mainloop_close
(
&
descr
);
err3:
lxc_console_sigwinch_fini
(
args
->
ts
);
err2:
close
(
args
->
ts
->
masterfd
);
err1:
tcsetattr
(
args
->
ptyfd
,
TCSAFLUSH
,
&
oldtios
);
if
(
pid
>
0
)
ret
=
lxc_wait_for_pid_status
(
pid
);
return
ret
;
}
static
int
pty_on_host_callback
(
void
*
p
)
{
struct
wrapargs
*
wrap
=
p
;
close
(
wrap
->
console
->
master
);
setsid
();
ioctl
(
wrap
->
console
->
slave
,
TIOCSCTTY
,
NULL
);
if
(
lxc_console_set_stdfds
(
wrap
->
console
->
slave
)
<
0
)
return
-
1
;
if
(
wrap
->
command
->
program
)
lxc_attach_run_command
(
wrap
->
command
);
else
lxc_attach_run_shell
(
NULL
);
return
-
1
;
}
static
int
pty_on_host
(
struct
lxc_container
*
c
,
struct
wrapargs
*
wrap
,
int
*
pid
)
{
int
ret
=
-
1
;
struct
wrapargs
*
args
=
wrap
;
struct
lxc_epoll_descr
descr
;
struct
lxc_conf
*
conf
;
struct
lxc_tty_state
*
ts
;
INFO
(
"Trying to allocate a pty on the host"
);
if
(
!
isatty
(
args
->
ptyfd
))
{
ERROR
(
"stdin is not a tty"
);
return
-
1
;
}
conf
=
c
->
lxc_conf
;
/* Create pty on the host. */
if
(
lxc_console_create
(
conf
)
<
0
)
return
-
1
;
ts
=
conf
->
console
.
tty_state
;
/* Shift ttys to container. */
if
(
ttys_shift_ids
(
conf
)
<
0
)
{
ERROR
(
"Failed to shift tty into container"
);
goto
err1
;
}
/* Send wrapper function on its way. */
wrap
->
console
=
&
conf
->
console
;
if
(
c
->
attach
(
c
,
pty_on_host_callback
,
wrap
,
wrap
->
options
,
pid
)
<
0
)
goto
err1
;
close
(
conf
->
console
.
slave
);
/* Close slave side. */
ret
=
lxc_mainloop_open
(
&
descr
);
if
(
ret
)
{
ERROR
(
"failed to create mainloop"
);
goto
err2
;
}
/* Register sigwinch handler in mainloop. */
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"
);
goto
err3
;
}
ret
=
lxc_mainloop
(
&
descr
,
-
1
);
if
(
ret
)
{
ERROR
(
"mainloop returned an error"
);
goto
err3
;
}
ret
=
0
;
err3:
lxc_mainloop_close
(
&
descr
);
err2:
lxc_console_sigwinch_fini
(
ts
);
err1:
lxc_console_delete
(
&
conf
->
console
);
return
ret
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
ret
=
-
1
;
pid_t
pid
;
pid_t
pid
;
lxc_attach_options_t
attach_options
=
LXC_ATTACH_OPTIONS_DEFAULT
;
lxc_attach_options_t
attach_options
=
LXC_ATTACH_OPTIONS_DEFAULT
;
lxc_attach_command_t
command
;
lxc_attach_command_t
command
=
(
lxc_attach_command_t
){.
program
=
NULL
}
;
ret
=
lxc_caps_init
();
ret
=
lxc_caps_init
();
if
(
ret
)
if
(
ret
)
return
1
;
exit
(
EXIT_FAILURE
)
;
ret
=
lxc_arguments_parse
(
&
my_args
,
argc
,
argv
);
ret
=
lxc_arguments_parse
(
&
my_args
,
argc
,
argv
);
if
(
ret
)
if
(
ret
)
return
1
;
exit
(
EXIT_FAILURE
)
;
if
(
!
my_args
.
log_file
)
if
(
!
my_args
.
log_file
)
my_args
.
log_file
=
"none"
;
my_args
.
log_file
=
"none"
;
...
@@ -207,9 +458,33 @@ int main(int argc, char *argv[])
...
@@ -207,9 +458,33 @@ int main(int argc, char *argv[])
ret
=
lxc_log_init
(
my_args
.
name
,
my_args
.
log_file
,
my_args
.
log_priority
,
ret
=
lxc_log_init
(
my_args
.
name
,
my_args
.
log_file
,
my_args
.
log_priority
,
my_args
.
progname
,
my_args
.
quiet
,
my_args
.
lxcpath
[
0
]);
my_args
.
progname
,
my_args
.
quiet
,
my_args
.
lxcpath
[
0
]);
if
(
ret
)
if
(
ret
)
return
1
;
exit
(
EXIT_FAILURE
)
;
lxc_log_options_no_override
();
lxc_log_options_no_override
();
if
(
geteuid
())
{
if
(
access
(
my_args
.
lxcpath
[
0
],
O_RDWR
)
<
0
)
{
if
(
!
my_args
.
quiet
)
fprintf
(
stderr
,
"You lack access to %s
\n
"
,
my_args
.
lxcpath
[
0
]);
exit
(
ret
);
}
}
struct
lxc_container
*
c
=
lxc_container_new
(
my_args
.
name
,
my_args
.
lxcpath
[
0
]);
if
(
!
c
)
exit
(
EXIT_FAILURE
);
if
(
!
c
->
may_control
(
c
))
{
fprintf
(
stderr
,
"Insufficent privileges to control %s
\n
"
,
c
->
name
);
lxc_container_put
(
c
);
exit
(
EXIT_FAILURE
);
}
if
(
!
c
->
is_defined
(
c
))
{
fprintf
(
stderr
,
"Error: container %s is not defined
\n
"
,
c
->
name
);
lxc_container_put
(
c
);
exit
(
EXIT_FAILURE
);
}
if
(
remount_sys_proc
)
if
(
remount_sys_proc
)
attach_options
.
attach_flags
|=
LXC_ATTACH_REMOUNT_PROC_SYS
;
attach_options
.
attach_flags
|=
LXC_ATTACH_REMOUNT_PROC_SYS
;
if
(
elevated_privileges
)
if
(
elevated_privileges
)
...
@@ -220,23 +495,41 @@ int main(int argc, char *argv[])
...
@@ -220,23 +495,41 @@ int main(int argc, char *argv[])
attach_options
.
extra_env_vars
=
extra_env
;
attach_options
.
extra_env_vars
=
extra_env
;
attach_options
.
extra_keep_env
=
extra_keep
;
attach_options
.
extra_keep_env
=
extra_keep
;
if
(
my_args
.
argc
)
{
struct
wrapargs
wrap
=
(
struct
wrapargs
){.
command
=
&
command
,
command
.
program
=
my_args
.
argv
[
0
];
.
options
=
&
attach_options
};
command
.
argv
=
(
char
**
)
my_args
.
argv
;
if
(
my_args
.
argc
>
0
)
{
ret
=
lxc_attach
(
my_args
.
name
,
my_args
.
lxcpath
[
0
],
lxc_attach_run_command
,
&
command
,
&
attach_options
,
&
pid
);
wrap
.
command
->
program
=
my_args
.
argv
[
0
];
wrap
.
command
->
argv
=
(
char
**
)
my_args
.
argv
;
}
if
(
isatty
(
STDIN_FILENO
)
||
isatty
(
STDOUT_FILENO
)
||
isatty
(
STDERR_FILENO
))
{
if
(
isatty
(
STDIN_FILENO
))
wrap
.
ptyfd
=
STDIN_FILENO
;
else
if
(
isatty
(
STDOUT_FILENO
))
wrap
.
ptyfd
=
STDOUT_FILENO
;
else
if
(
isatty
(
STDERR_FILENO
))
wrap
.
ptyfd
=
STDERR_FILENO
;
ret
=
c
->
attach
(
c
,
pty_in_container
,
&
wrap
,
&
attach_options
,
&
pid
);
if
(
ret
<
0
)
ret
=
pty_on_host
(
c
,
&
wrap
,
&
pid
);
}
else
{
}
else
{
ret
=
lxc_attach
(
my_args
.
name
,
my_args
.
lxcpath
[
0
],
lxc_attach_run_shell
,
NULL
,
&
attach_options
,
&
pid
);
if
(
my_args
.
argc
>
1
)
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
);
}
}
lxc_container_put
(
c
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
1
;
exit
(
EXIT_FAILURE
)
;
ret
=
lxc_wait_for_pid_status
(
pid
);
ret
=
lxc_wait_for_pid_status
(
pid
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
1
;
exit
(
EXIT_FAILURE
)
;
if
(
WIFEXITED
(
ret
))
if
(
WIFEXITED
(
ret
))
return
WEXITSTATUS
(
ret
);
return
WEXITSTATUS
(
ret
);
return
1
;
exit
(
EXIT_FAILURE
)
;
}
}
src/lxc/start.c
View file @
cee1de17
...
@@ -798,7 +798,7 @@ static int do_start(void *data)
...
@@ -798,7 +798,7 @@ static int do_start(void *data)
* setup on its console ie. the pty allocated in lxc_console_create()
* setup on its console ie. the pty allocated in lxc_console_create()
* so make sure that that pty is stdin,stdout,stderr.
* so make sure that that pty is stdin,stdout,stderr.
*/
*/
if
(
lxc_console_set_stdfds
(
handler
)
<
0
)
if
(
lxc_console_set_stdfds
(
handler
->
conf
->
console
.
slave
)
<
0
)
goto
out_warn_father
;
goto
out_warn_father
;
/* If we mounted a temporary proc, then unmount it now */
/* If we mounted a temporary proc, then unmount it now */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment