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
ff305221
Unverified
Commit
ff305221
authored
Feb 28, 2018
by
Serge Hallyn
Committed by
GitHub
Feb 28, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2196 from brauner/2018-02-28/more_terminal_fixes
terminal: improvements and cleanup
parents
19462d43
e9a55b51
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
267 additions
and
225 deletions
+267
-225
attach.c
src/lxc/attach.c
+2
-2
mainloop.h
src/lxc/mainloop.h
+1
-0
terminal.c
src/lxc/terminal.c
+175
-142
terminal.h
src/lxc/terminal.h
+89
-81
No files found.
src/lxc/attach.c
View file @
ff305221
...
@@ -846,7 +846,7 @@ static int attach_child_main(struct attach_clone_payload *payload)
...
@@ -846,7 +846,7 @@ static int attach_child_main(struct attach_clone_payload *payload)
}
}
if
(
options
->
stdin_fd
>
0
&&
isatty
(
options
->
stdin_fd
))
{
if
(
options
->
stdin_fd
>
0
&&
isatty
(
options
->
stdin_fd
))
{
ret
=
lxc_make_controlling_
pty
(
options
->
stdin_fd
);
ret
=
lxc_make_controlling_
terminal
(
options
->
stdin_fd
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
on_error
;
goto
on_error
;
}
}
...
@@ -958,7 +958,7 @@ static int attach_child_main(struct attach_clone_payload *payload)
...
@@ -958,7 +958,7 @@ static int attach_child_main(struct attach_clone_payload *payload)
}
}
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
{
if
(
options
->
attach_flags
&
LXC_ATTACH_ALLOCATE_PTY
)
{
ret
=
lxc_
login_pty
(
payload
->
pty_fd
);
ret
=
lxc_
terminal_prepare_login
(
payload
->
pty_fd
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to prepare pty file descriptor %d"
,
payload
->
pty_fd
);
SYSERROR
(
"Failed to prepare pty file descriptor %d"
,
payload
->
pty_fd
);
goto
on_error
;
goto
on_error
;
...
...
src/lxc/mainloop.h
View file @
ff305221
...
@@ -27,6 +27,7 @@
...
@@ -27,6 +27,7 @@
#include <stdint.h>
#include <stdint.h>
#include "list.h"
#include "list.h"
#define LXC_MAINLOOP_ERROR -1
#define LXC_MAINLOOP_CONTINUE 0
#define LXC_MAINLOOP_CONTINUE 0
#define LXC_MAINLOOP_CLOSE 1
#define LXC_MAINLOOP_CLOSE 1
...
...
src/lxc/terminal.c
View file @
ff305221
...
@@ -23,15 +23,14 @@
...
@@ -23,15 +23,14 @@
#include <errno.h>
#include <errno.h>
#include <fcntl.h>
#include <fcntl.h>
#include <lxc/lxccontainer.h>
#include <signal.h>
#include <signal.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/types.h>
#include <termios.h>
#include <
lxc/lxccontainer
.h>
#include <
unistd
.h>
#include "af_unix.h"
#include "af_unix.h"
#include "caps.h"
#include "caps.h"
...
@@ -41,7 +40,7 @@
...
@@ -41,7 +40,7 @@
#include "log.h"
#include "log.h"
#include "lxclock.h"
#include "lxclock.h"
#include "mainloop.h"
#include "mainloop.h"
#include "start.h"
/* for struct lxc_handler */
#include "start.h"
#include "terminal.h"
#include "terminal.h"
#include "utils.h"
#include "utils.h"
...
@@ -117,7 +116,7 @@ int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata,
...
@@ -117,7 +116,7 @@ int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata,
ret
=
read
(
fd
,
&
siginfo
,
sizeof
(
siginfo
));
ret
=
read
(
fd
,
&
siginfo
,
sizeof
(
siginfo
));
if
(
ret
<
0
||
(
size_t
)
ret
<
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
LXC_MAINLOOP_ERROR
;
}
}
if
(
siginfo
.
ssi_signo
==
SIGTERM
)
{
if
(
siginfo
.
ssi_signo
==
SIGTERM
)
{
...
@@ -128,13 +127,13 @@ int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata,
...
@@ -128,13 +127,13 @@ int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata,
if
(
siginfo
.
ssi_signo
==
SIGWINCH
)
if
(
siginfo
.
ssi_signo
==
SIGWINCH
)
lxc_terminal_winch
(
ts
);
lxc_terminal_winch
(
ts
);
return
0
;
return
LXC_MAINLOOP_CONTINUE
;
}
}
struct
lxc_terminal_state
*
lxc_terminal_signal_init
(
int
srcfd
,
int
dstfd
)
struct
lxc_terminal_state
*
lxc_terminal_signal_init
(
int
srcfd
,
int
dstfd
)
{
{
int
ret
;
int
ret
;
bool
istty
;
bool
istty
=
false
;
sigset_t
mask
;
sigset_t
mask
;
struct
lxc_terminal_state
*
ts
;
struct
lxc_terminal_state
*
ts
;
...
@@ -147,20 +146,31 @@ struct lxc_terminal_state *lxc_terminal_signal_init(int srcfd, int dstfd)
...
@@ -147,20 +146,31 @@ struct lxc_terminal_state *lxc_terminal_signal_init(int srcfd, int dstfd)
ts
->
masterfd
=
dstfd
;
ts
->
masterfd
=
dstfd
;
ts
->
sigfd
=
-
1
;
ts
->
sigfd
=
-
1
;
sigemptyset
(
&
mask
);
ret
=
sigemptyset
(
&
mask
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to initialize an empty signal set"
);
goto
on_error
;
}
istty
=
isatty
(
srcfd
)
==
1
;
istty
=
(
isatty
(
srcfd
)
==
1
)
;
if
(
!
istty
)
{
if
(
!
istty
)
{
INFO
(
"fd %d does not refer to a tty device"
,
srcfd
);
INFO
(
"fd %d does not refer to a tty device"
,
srcfd
);
}
else
{
}
else
{
/* Add tty to list to be scanned at SIGWINCH time. */
/* Add tty to list to be scanned at SIGWINCH time. */
lxc_list_add_elem
(
&
ts
->
node
,
ts
);
lxc_list_add_elem
(
&
ts
->
node
,
ts
);
lxc_list_add_tail
(
&
lxc_ttys
,
&
ts
->
node
);
lxc_list_add_tail
(
&
lxc_ttys
,
&
ts
->
node
);
sigaddset
(
&
mask
,
SIGWINCH
);
ret
=
sigaddset
(
&
mask
,
SIGWINCH
);
if
(
ret
<
0
)
NOTICE
(
"%s - Failed to add SIGWINCH to signal set"
,
strerror
(
errno
));
}
}
/* Exit the mainloop cleanly on SIGTERM. */
/* Exit the mainloop cleanly on SIGTERM. */
sigaddset
(
&
mask
,
SIGTERM
);
ret
=
sigaddset
(
&
mask
,
SIGTERM
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to add SIGWINCH to signal set"
);
goto
on_error
;
}
ret
=
sigprocmask
(
SIG_BLOCK
,
&
mask
,
&
ts
->
oldmask
);
ret
=
sigprocmask
(
SIG_BLOCK
,
&
mask
,
&
ts
->
oldmask
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
...
@@ -184,8 +194,10 @@ on_error:
...
@@ -184,8 +194,10 @@ on_error:
close
(
ts
->
sigfd
);
close
(
ts
->
sigfd
);
ts
->
sigfd
=
-
1
;
ts
->
sigfd
=
-
1
;
}
}
if
(
istty
)
if
(
istty
)
lxc_list_del
(
&
ts
->
node
);
lxc_list_del
(
&
ts
->
node
);
return
ts
;
return
ts
;
}
}
...
@@ -243,11 +255,11 @@ static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal)
...
@@ -243,11 +255,11 @@ static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal)
}
}
static
int
lxc_terminal_write_log_file
(
struct
lxc_terminal
*
terminal
,
char
*
buf
,
static
int
lxc_terminal_write_log_file
(
struct
lxc_terminal
*
terminal
,
char
*
buf
,
int
bytes_read
)
int
bytes_read
)
{
{
int
ret
;
int
ret
;
int64_t
space_left
=
-
1
;
struct
stat
st
;
struct
stat
st
;
int64_t
space_left
=
-
1
;
if
(
terminal
->
log_fd
<
0
)
if
(
terminal
->
log_fd
<
0
)
return
0
;
return
0
;
...
@@ -404,7 +416,7 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data,
...
@@ -404,7 +416,7 @@ int lxc_terminal_io_cb(int fd, uint32_t events, void *data,
if
(
w_log
<
0
)
if
(
w_log
<
0
)
TRACE
(
"Failed to write %d bytes to terminal log"
,
r
);
TRACE
(
"Failed to write %d bytes to terminal log"
,
r
);
return
0
;
return
LXC_MAINLOOP_CONTINUE
;
}
}
static
int
lxc_terminal_mainloop_add_peer
(
struct
lxc_terminal
*
terminal
)
static
int
lxc_terminal_mainloop_add_peer
(
struct
lxc_terminal
*
terminal
)
...
@@ -434,7 +446,7 @@ static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal)
...
@@ -434,7 +446,7 @@ static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal)
}
}
int
lxc_terminal_mainloop_add
(
struct
lxc_epoll_descr
*
descr
,
int
lxc_terminal_mainloop_add
(
struct
lxc_epoll_descr
*
descr
,
struct
lxc_terminal
*
terminal
)
struct
lxc_terminal
*
terminal
)
{
{
int
ret
;
int
ret
;
...
@@ -446,7 +458,8 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr,
...
@@ -446,7 +458,8 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr,
ret
=
lxc_mainloop_add_handler
(
descr
,
terminal
->
master
,
ret
=
lxc_mainloop_add_handler
(
descr
,
terminal
->
master
,
lxc_terminal_io_cb
,
terminal
);
lxc_terminal_io_cb
,
terminal
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ERROR
(
"Failed to add handler for %d to mainloop"
,
terminal
->
master
);
ERROR
(
"Failed to add handler for terminal master fd %d to "
"mainloop"
,
terminal
->
master
);
return
-
1
;
return
-
1
;
}
}
...
@@ -454,25 +467,24 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr,
...
@@ -454,25 +467,24 @@ int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr,
* does attach to it in lxc_terminal_allocate().
* does attach to it in lxc_terminal_allocate().
*/
*/
terminal
->
descr
=
descr
;
terminal
->
descr
=
descr
;
ret
=
lxc_terminal_mainloop_add_peer
(
terminal
);
if
(
ret
<
0
)
return
-
1
;
return
0
;
return
lxc_terminal_mainloop_add_peer
(
terminal
)
;
}
}
int
lxc_setup_tios
(
int
fd
,
struct
termios
*
oldtios
)
int
lxc_setup_tios
(
int
fd
,
struct
termios
*
oldtios
)
{
{
int
ret
;
struct
termios
newtios
;
struct
termios
newtios
;
if
(
!
isatty
(
fd
))
{
if
(
!
isatty
(
fd
))
{
ERROR
(
"
'%d' is not a tty
"
,
fd
);
ERROR
(
"
File descriptor %d does not refert to a terminal
"
,
fd
);
return
-
1
;
return
-
1
;
}
}
/* Get current termios */
/* Get current termios. */
if
(
tcgetattr
(
fd
,
oldtios
))
{
ret
=
tcgetattr
(
fd
,
oldtios
);
SYSERROR
(
"failed to get current terminal settings"
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to get current terminal settings"
);
return
-
1
;
return
-
1
;
}
}
...
@@ -501,8 +513,9 @@ int lxc_setup_tios(int fd, struct termios *oldtios)
...
@@ -501,8 +513,9 @@ int lxc_setup_tios(int fd, struct termios *oldtios)
newtios
.
c_cc
[
VTIME
]
=
0
;
newtios
.
c_cc
[
VTIME
]
=
0
;
/* Set new attributes. */
/* Set new attributes. */
if
(
tcsetattr
(
fd
,
TCSAFLUSH
,
&
newtios
))
{
ret
=
tcsetattr
(
fd
,
TCSAFLUSH
,
&
newtios
);
ERROR
(
"failed to set new terminal settings"
);
if
(
ret
<
0
)
{
ERROR
(
"Failed to set new terminal settings"
);
return
-
1
;
return
-
1
;
}
}
...
@@ -515,75 +528,90 @@ static void lxc_terminal_peer_proxy_free(struct lxc_terminal *terminal)
...
@@ -515,75 +528,90 @@ static void lxc_terminal_peer_proxy_free(struct lxc_terminal *terminal)
lxc_terminal_signal_fini
(
terminal
->
tty_state
);
lxc_terminal_signal_fini
(
terminal
->
tty_state
);
terminal
->
tty_state
=
NULL
;
terminal
->
tty_state
=
NULL
;
}
}
close
(
terminal
->
proxy
.
master
);
close
(
terminal
->
proxy
.
master
);
close
(
terminal
->
proxy
.
slave
);
terminal
->
proxy
.
master
=
-
1
;
terminal
->
proxy
.
master
=
-
1
;
close
(
terminal
->
proxy
.
slave
);
terminal
->
proxy
.
slave
=
-
1
;
terminal
->
proxy
.
slave
=
-
1
;
terminal
->
proxy
.
busy
=
-
1
;
terminal
->
proxy
.
busy
=
-
1
;
terminal
->
proxy
.
name
[
0
]
=
'\0'
;
terminal
->
proxy
.
name
[
0
]
=
'\0'
;
terminal
->
peer
=
-
1
;
terminal
->
peer
=
-
1
;
}
}
static
int
lxc_terminal_peer_proxy_alloc
(
struct
lxc_terminal
*
terminal
,
int
sockfd
)
static
int
lxc_terminal_peer_proxy_alloc
(
struct
lxc_terminal
*
terminal
,
int
sockfd
)
{
{
int
ret
;
struct
termios
oldtermio
;
struct
termios
oldtermio
;
struct
lxc_terminal_state
*
ts
;
struct
lxc_terminal_state
*
ts
;
int
ret
;
if
(
terminal
->
master
<
0
)
{
if
(
terminal
->
master
<
0
)
{
ERROR
(
"Terminal not set up"
);
ERROR
(
"Terminal not set up"
);
return
-
1
;
return
-
1
;
}
}
if
(
terminal
->
proxy
.
busy
!=
-
1
||
terminal
->
peer
!=
-
1
)
{
if
(
terminal
->
proxy
.
busy
!=
-
1
||
terminal
->
peer
!=
-
1
)
{
NOTICE
(
"Terminal already in use"
);
NOTICE
(
"Terminal already in use"
);
return
-
1
;
return
-
1
;
}
}
if
(
terminal
->
tty_state
)
{
if
(
terminal
->
tty_state
)
{
ERROR
(
"Terminal
already has tty_state
"
);
ERROR
(
"Terminal
has already been initialized
"
);
return
-
1
;
return
-
1
;
}
}
/*
this is the proxy pty that will be given to the client, and that
/*
This is the proxy terminal that will be given to the client, and
* th
e real pty master will send to / recv from
* th
at the real terminal master will send to / recv from.
*/
*/
ret
=
openpty
(
&
terminal
->
proxy
.
master
,
&
terminal
->
proxy
.
slave
,
ret
=
openpty
(
&
terminal
->
proxy
.
master
,
&
terminal
->
proxy
.
slave
,
terminal
->
proxy
.
name
,
NULL
,
NULL
);
terminal
->
proxy
.
name
,
NULL
,
NULL
);
if
(
ret
)
{
if
(
ret
<
0
)
{
SYSERROR
(
"
failed to create proxy pty
"
);
SYSERROR
(
"
Failed to open proxy terminal
"
);
return
-
1
;
return
-
1
;
}
}
if
(
lxc_setup_tios
(
terminal
->
proxy
.
slave
,
&
oldtermio
)
<
0
)
ret
=
lxc_setup_tios
(
terminal
->
proxy
.
slave
,
&
oldtermio
);
goto
err1
;
if
(
ret
<
0
)
goto
on_error
;
ts
=
lxc_terminal_signal_init
(
terminal
->
proxy
.
master
,
terminal
->
master
);
ts
=
lxc_terminal_signal_init
(
terminal
->
proxy
.
master
,
terminal
->
master
);
if
(
!
ts
)
if
(
!
ts
)
goto
err1
;
goto
on_error
;
terminal
->
tty_state
=
ts
;
terminal
->
tty_state
=
ts
;
terminal
->
peer
=
terminal
->
proxy
.
slave
;
terminal
->
peer
=
terminal
->
proxy
.
slave
;
terminal
->
proxy
.
busy
=
sockfd
;
terminal
->
proxy
.
busy
=
sockfd
;
ret
=
lxc_terminal_mainloop_add_peer
(
terminal
);
ret
=
lxc_terminal_mainloop_add_peer
(
terminal
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
err1
;
goto
on_error
;
DEBUG
(
"%d peermaster:%d sockfd:%d"
,
lxc_raw_getpid
(),
terminal
->
proxy
.
master
,
sockfd
);
NOTICE
(
"Opened proxy terminal with master fd %d and slave fd %d"
,
terminal
->
proxy
.
master
,
terminal
->
proxy
.
slave
);
return
0
;
return
0
;
err1
:
on_error
:
lxc_terminal_peer_proxy_free
(
terminal
);
lxc_terminal_peer_proxy_free
(
terminal
);
return
-
1
;
return
-
1
;
}
}
int
lxc_terminal_allocate
(
struct
lxc_conf
*
conf
,
int
sockfd
,
int
*
ttyreq
)
int
lxc_terminal_allocate
(
struct
lxc_conf
*
conf
,
int
sockfd
,
int
*
ttyreq
)
{
{
int
masterfd
=
-
1
,
ttynum
;
int
ttynum
;
int
masterfd
=
-
1
;
struct
lxc_tty_info
*
ttys
=
&
conf
->
ttys
;
struct
lxc_tty_info
*
ttys
=
&
conf
->
ttys
;
struct
lxc_terminal
*
terminal
=
&
conf
->
console
;
struct
lxc_terminal
*
terminal
=
&
conf
->
console
;
if
(
*
ttyreq
==
0
)
{
if
(
*
ttyreq
==
0
)
{
if
(
lxc_terminal_peer_proxy_alloc
(
terminal
,
sockfd
)
<
0
)
int
ret
;
ret
=
lxc_terminal_peer_proxy_alloc
(
terminal
,
sockfd
);
if
(
ret
<
0
)
goto
out
;
goto
out
;
masterfd
=
terminal
->
proxy
.
master
;
masterfd
=
terminal
->
proxy
.
master
;
goto
out
;
goto
out
;
}
}
...
@@ -595,16 +623,17 @@ int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
...
@@ -595,16 +623,17 @@ int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
if
(
ttys
->
tty
[
*
ttyreq
-
1
].
busy
)
if
(
ttys
->
tty
[
*
ttyreq
-
1
].
busy
)
goto
out
;
goto
out
;
/*
the requested tty is available
*/
/*
The requested tty is available.
*/
ttynum
=
*
ttyreq
;
ttynum
=
*
ttyreq
;
goto
out_tty
;
goto
out_tty
;
}
}
/*
search for next available tty, fixup index tty1 => [0]
*/
/*
Search for next available tty, fixup index tty1 => [0].
*/
for
(
ttynum
=
1
;
ttynum
<=
ttys
->
nbtty
&&
ttys
->
tty
[
ttynum
-
1
].
busy
;
ttynum
++
)
for
(
ttynum
=
1
;
ttynum
<=
ttys
->
nbtty
&&
ttys
->
tty
[
ttynum
-
1
].
busy
;
ttynum
++
)
{
;
;
}
/*
we didn't find any available slot for tty
*/
/*
We didn't find any available slot for tty.
*/
if
(
ttynum
>
ttys
->
nbtty
)
if
(
ttynum
>
ttys
->
nbtty
)
goto
out
;
goto
out
;
...
@@ -613,6 +642,7 @@ int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
...
@@ -613,6 +642,7 @@ int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
out_tty
:
out_tty
:
ttys
->
tty
[
ttynum
-
1
].
busy
=
sockfd
;
ttys
->
tty
[
ttynum
-
1
].
busy
=
sockfd
;
masterfd
=
ttys
->
tty
[
ttynum
-
1
].
master
;
masterfd
=
ttys
->
tty
[
ttynum
-
1
].
master
;
out
:
out
:
return
masterfd
;
return
masterfd
;
}
}
...
@@ -623,15 +653,15 @@ void lxc_terminal_free(struct lxc_conf *conf, int fd)
...
@@ -623,15 +653,15 @@ void lxc_terminal_free(struct lxc_conf *conf, int fd)
struct
lxc_tty_info
*
ttys
=
&
conf
->
ttys
;
struct
lxc_tty_info
*
ttys
=
&
conf
->
ttys
;
struct
lxc_terminal
*
terminal
=
&
conf
->
console
;
struct
lxc_terminal
*
terminal
=
&
conf
->
console
;
for
(
i
=
0
;
i
<
ttys
->
nbtty
;
i
++
)
{
for
(
i
=
0
;
i
<
ttys
->
nbtty
;
i
++
)
if
(
ttys
->
tty
[
i
].
busy
==
fd
)
if
(
ttys
->
tty
[
i
].
busy
==
fd
)
ttys
->
tty
[
i
].
busy
=
0
;
ttys
->
tty
[
i
].
busy
=
0
;
}
if
(
terminal
->
proxy
.
busy
==
fd
)
{
if
(
terminal
->
proxy
.
busy
!=
fd
)
lxc_mainloop_del_handler
(
terminal
->
descr
,
terminal
->
proxy
.
slave
);
return
;
lxc_terminal_peer_proxy_free
(
terminal
);
}
lxc_mainloop_del_handler
(
terminal
->
descr
,
terminal
->
proxy
.
slave
);
lxc_terminal_peer_proxy_free
(
terminal
);
}
}
static
int
lxc_terminal_peer_default
(
struct
lxc_terminal
*
terminal
)
static
int
lxc_terminal_peer_default
(
struct
lxc_terminal
*
terminal
)
...
@@ -641,65 +671,69 @@ static int lxc_terminal_peer_default(struct lxc_terminal *terminal)
...
@@ -641,65 +671,69 @@ static int lxc_terminal_peer_default(struct lxc_terminal *terminal)
int
fd
;
int
fd
;
int
ret
=
0
;
int
ret
=
0
;
/* If no terminal was given, try current controlling terminal, there
if
(
!
path
)
{
* won't be one if we were started as a daemon (-d).
ret
=
access
(
"/dev/tty"
,
F_OK
);
*/
if
(
ret
==
0
)
{
if
(
!
path
&&
!
access
(
"/dev/tty"
,
F_OK
))
{
/* If no terminal was given, try current controlling
fd
=
open
(
"/dev/tty"
,
O_RDWR
);
* terminal, there won't be one if we were started as a
if
(
fd
>=
0
)
{
* daemon (-d).
close
(
fd
);
*/
path
=
"/dev/tty"
;
fd
=
open
(
"/dev/tty"
,
O_RDWR
);
if
(
fd
>=
0
)
{
close
(
fd
);
path
=
"/dev/tty"
;
}
}
}
}
}
if
(
!
path
)
{
if
(
!
path
)
{
errno
=
ENOTTY
;
errno
=
ENOTTY
;
DEBUG
(
"process does not have a controlling terminal"
);
DEBUG
(
"
Theh
process does not have a controlling terminal"
);
goto
o
ut
;
goto
o
n_succes
;
}
}
terminal
->
peer
=
lxc_unpriv
(
open
(
path
,
O_RDWR
|
O_CLOEXEC
));
terminal
->
peer
=
lxc_unpriv
(
open
(
path
,
O_RDWR
|
O_CLOEXEC
));
if
(
terminal
->
peer
<
0
)
{
if
(
terminal
->
peer
<
0
)
{
ERROR
(
"Failed to open
\"
%s
\"
: %s"
,
path
,
strerror
(
errno
));
ERROR
(
"%s - Failed to open proxy terminal
\"
%s
\"
"
,
strerror
(
errno
),
path
);
return
-
ENOTTY
;
return
-
ENOTTY
;
}
}
DEBUG
(
"
using
\"
%s
\"
as peer tty device
"
,
path
);
DEBUG
(
"
Using terminal
\"
%s
\"
as proxy
"
,
path
);
if
(
!
isatty
(
terminal
->
peer
))
{
if
(
!
isatty
(
terminal
->
peer
))
{
ERROR
(
"
file descriptor for file
\"
%s
\"
does not refer to a tty device
"
,
path
);
ERROR
(
"
File descriptor for
\"
%s
\"
does not refer to a terminal
"
,
path
);
goto
on_error
1
;
goto
on_error
_free_tios
;
}
}
ts
=
lxc_terminal_signal_init
(
terminal
->
peer
,
terminal
->
master
);
ts
=
lxc_terminal_signal_init
(
terminal
->
peer
,
terminal
->
master
);
terminal
->
tty_state
=
ts
;
terminal
->
tty_state
=
ts
;
if
(
!
ts
)
{
if
(
!
ts
)
{
WARN
(
"Failed to install signal handler"
);
WARN
(
"Failed to install signal handler"
);
goto
on_error
1
;
goto
on_error
_free_tios
;
}
}
lxc_terminal_winsz
(
terminal
->
peer
,
terminal
->
master
);
lxc_terminal_winsz
(
terminal
->
peer
,
terminal
->
master
);
terminal
->
tios
=
malloc
(
sizeof
(
*
terminal
->
tios
));
terminal
->
tios
=
malloc
(
sizeof
(
*
terminal
->
tios
));
if
(
!
terminal
->
tios
)
{
if
(
!
terminal
->
tios
)
SYSERROR
(
"failed to allocate memory"
);
goto
on_error_free_tios
;
goto
on_error1
;
}
if
(
lxc_setup_tios
(
terminal
->
peer
,
terminal
->
tios
)
<
0
)
ret
=
lxc_setup_tios
(
terminal
->
peer
,
terminal
->
tios
);
goto
on_error2
;
if
(
ret
<
0
)
goto
on_error_close_peer
;
else
else
goto
o
ut
;
goto
o
n_succes
;
on_error
2
:
on_error
_free_tios
:
free
(
terminal
->
tios
);
free
(
terminal
->
tios
);
terminal
->
tios
=
NULL
;
terminal
->
tios
=
NULL
;
on_error
1
:
on_error
_close_peer
:
close
(
terminal
->
peer
);
close
(
terminal
->
peer
);
terminal
->
peer
=
-
1
;
terminal
->
peer
=
-
1
;
ret
=
-
ENOTTY
;
ret
=
-
ENOTTY
;
o
ut
:
o
n_succes
:
return
ret
;
return
ret
;
}
}
...
@@ -835,13 +869,11 @@ int lxc_terminal_create_log_file(struct lxc_terminal *terminal)
...
@@ -835,13 +869,11 @@ int lxc_terminal_create_log_file(struct lxc_terminal *terminal)
int
lxc_terminal_create
(
struct
lxc_terminal
*
terminal
)
int
lxc_terminal_create
(
struct
lxc_terminal
*
terminal
)
{
{
int
ret
,
saved_errno
;
int
ret
;
ret
=
openpty
(
&
terminal
->
master
,
&
terminal
->
slave
,
terminal
->
name
,
NULL
,
ret
=
openpty
(
&
terminal
->
master
,
&
terminal
->
slave
,
terminal
->
name
,
NULL
,
NULL
);
NULL
);
saved_errno
=
errno
;
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ERROR
(
"%s - Failed to allocate a pty"
,
strerror
(
saved_errno
)
);
SYSERROR
(
"Failed to open terminal"
);
return
-
1
;
return
-
1
;
}
}
...
@@ -859,7 +891,7 @@ int lxc_terminal_create(struct lxc_terminal *terminal)
...
@@ -859,7 +891,7 @@ int lxc_terminal_create(struct lxc_terminal *terminal)
ret
=
lxc_terminal_peer_default
(
terminal
);
ret
=
lxc_terminal_peer_default
(
terminal
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ERROR
(
"Failed to allocate
a peer pty device
"
);
ERROR
(
"Failed to allocate
proxy terminal
"
);
goto
err
;
goto
err
;
}
}
...
@@ -875,8 +907,8 @@ int lxc_terminal_setup(struct lxc_conf *conf)
...
@@ -875,8 +907,8 @@ int lxc_terminal_setup(struct lxc_conf *conf)
int
ret
;
int
ret
;
struct
lxc_terminal
*
terminal
=
&
conf
->
console
;
struct
lxc_terminal
*
terminal
=
&
conf
->
console
;
if
(
terminal
->
path
&&
!
strcmp
(
terminal
->
path
,
"none"
)
)
{
if
(
terminal
->
path
&&
strcmp
(
terminal
->
path
,
"none"
)
==
0
)
{
INFO
(
"No terminal
was
requested"
);
INFO
(
"No terminal requested"
);
return
0
;
return
0
;
}
}
...
@@ -884,12 +916,10 @@ int lxc_terminal_setup(struct lxc_conf *conf)
...
@@ -884,12 +916,10 @@ int lxc_terminal_setup(struct lxc_conf *conf)
if
(
ret
<
0
)
if
(
ret
<
0
)
return
-
1
;
return
-
1
;
/* create terminal log file */
ret
=
lxc_terminal_create_log_file
(
terminal
);
ret
=
lxc_terminal_create_log_file
(
terminal
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
err
;
goto
err
;
/* create terminal ringbuffer */
ret
=
lxc_terminal_create_ringbuf
(
terminal
);
ret
=
lxc_terminal_create_ringbuf
(
terminal
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
err
;
goto
err
;
...
@@ -901,49 +931,56 @@ err:
...
@@ -901,49 +931,56 @@ err:
return
-
ENODEV
;
return
-
ENODEV
;
}
}
static
bool
__terminal_dup2
(
int
duplicate
,
int
original
)
{
int
ret
;
if
(
!
isatty
(
original
))
return
true
;
ret
=
dup2
(
duplicate
,
original
);
if
(
ret
<
0
)
{
SYSERROR
(
"Failed to dup2(%d, %d)"
,
duplicate
,
original
);
return
false
;
}
return
true
;
}
int
lxc_terminal_set_stdfds
(
int
fd
)
int
lxc_terminal_set_stdfds
(
int
fd
)
{
{
int
i
;
if
(
fd
<
0
)
if
(
fd
<
0
)
return
0
;
return
0
;
if
(
isatty
(
STDIN_FILENO
))
for
(
i
=
0
;
i
<
3
;
i
++
)
if
(
dup2
(
fd
,
STDIN_FILENO
)
<
0
)
{
if
(
!
__terminal_dup2
(
fd
,
(
int
[]){
STDIN_FILENO
,
STDOUT_FILENO
,
SYSERROR
(
"failed to duplicate stdin."
);
STDERR_FILENO
}[
i
]))
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
-
1
;
}
return
0
;
return
0
;
}
}
int
lxc_terminal_stdin_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
int
lxc_terminal_stdin_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
)
struct
lxc_epoll_descr
*
descr
)
{
{
struct
lxc_terminal_state
*
ts
=
cbdata
;
int
ret
;
char
c
;
char
c
;
struct
lxc_terminal_state
*
ts
=
cbdata
;
if
(
fd
!=
ts
->
stdinfd
)
if
(
fd
!=
ts
->
stdinfd
)
return
LXC_MAINLOOP_CLOSE
;
return
LXC_MAINLOOP_CLOSE
;
if
(
lxc_read_nointr
(
ts
->
stdinfd
,
&
c
,
1
)
<=
0
)
ret
=
lxc_read_nointr
(
ts
->
stdinfd
,
&
c
,
1
);
if
(
ret
<=
0
)
return
LXC_MAINLOOP_CLOSE
;
return
LXC_MAINLOOP_CLOSE
;
if
(
ts
->
escape
>=
1
)
{
if
(
ts
->
escape
>=
1
)
{
/* we want to exit the terminal with Ctrl+a q */
/* we want to exit the terminal with Ctrl+a q */
if
(
c
==
ts
->
escape
&&
!
ts
->
saw_escape
)
{
if
(
c
==
ts
->
escape
&&
!
ts
->
saw_escape
)
{
ts
->
saw_escape
=
1
;
ts
->
saw_escape
=
1
;
return
0
;
return
LXC_MAINLOOP_CONTINUE
;
}
}
if
(
c
==
'q'
&&
ts
->
saw_escape
)
if
(
c
==
'q'
&&
ts
->
saw_escape
)
...
@@ -952,18 +989,19 @@ int lxc_terminal_stdin_cb(int fd, uint32_t events, void *cbdata,
...
@@ -952,18 +989,19 @@ int lxc_terminal_stdin_cb(int fd, uint32_t events, void *cbdata,
ts
->
saw_escape
=
0
;
ts
->
saw_escape
=
0
;
}
}
if
(
lxc_write_nointr
(
ts
->
masterfd
,
&
c
,
1
)
<=
0
)
ret
=
lxc_write_nointr
(
ts
->
masterfd
,
&
c
,
1
);
if
(
ret
<=
0
)
return
LXC_MAINLOOP_CLOSE
;
return
LXC_MAINLOOP_CLOSE
;
return
0
;
return
LXC_MAINLOOP_CONTINUE
;
}
}
int
lxc_terminal_master_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
int
lxc_terminal_master_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
)
struct
lxc_epoll_descr
*
descr
)
{
{
struct
lxc_terminal_state
*
ts
=
cbdata
;
char
buf
[
LXC_TERMINAL_BUFFER_SIZE
];
int
r
,
w
;
int
r
,
w
;
char
buf
[
LXC_TERMINAL_BUFFER_SIZE
];
struct
lxc_terminal_state
*
ts
=
cbdata
;
if
(
fd
!=
ts
->
masterfd
)
if
(
fd
!=
ts
->
masterfd
)
return
LXC_MAINLOOP_CLOSE
;
return
LXC_MAINLOOP_CLOSE
;
...
@@ -973,14 +1011,10 @@ int lxc_terminal_master_cb(int fd, uint32_t events, void *cbdata,
...
@@ -973,14 +1011,10 @@ int lxc_terminal_master_cb(int fd, uint32_t events, void *cbdata,
return
LXC_MAINLOOP_CLOSE
;
return
LXC_MAINLOOP_CLOSE
;
w
=
lxc_write_nointr
(
ts
->
stdoutfd
,
buf
,
r
);
w
=
lxc_write_nointr
(
ts
->
stdoutfd
,
buf
,
r
);
if
(
w
<=
0
)
{
if
(
w
<=
0
||
w
!=
r
)
return
LXC_MAINLOOP_CLOSE
;
return
LXC_MAINLOOP_CLOSE
;
}
else
if
(
w
!=
r
)
{
SYSERROR
(
"Failed to write"
);
return
1
;
}
return
0
;
return
LXC_MAINLOOP_CONTINUE
;
}
}
int
lxc_terminal_getfd
(
struct
lxc_container
*
c
,
int
*
ttynum
,
int
*
masterfd
)
int
lxc_terminal_getfd
(
struct
lxc_container
*
c
,
int
*
ttynum
,
int
*
masterfd
)
...
@@ -992,7 +1026,7 @@ int lxc_console(struct lxc_container *c, int ttynum,
...
@@ -992,7 +1026,7 @@ int lxc_console(struct lxc_container *c, int ttynum,
int
stdinfd
,
int
stdoutfd
,
int
stderrfd
,
int
stdinfd
,
int
stdoutfd
,
int
stderrfd
,
int
escape
)
int
escape
)
{
{
int
ret
,
ttyfd
,
master
fd
;
int
masterfd
,
ret
,
tty
fd
;
struct
lxc_epoll_descr
descr
;
struct
lxc_epoll_descr
descr
;
struct
termios
oldtios
;
struct
termios
oldtios
;
struct
lxc_terminal_state
*
ts
;
struct
lxc_terminal_state
*
ts
;
...
@@ -1021,7 +1055,7 @@ int lxc_console(struct lxc_container *c, int ttynum,
...
@@ -1021,7 +1055,7 @@ int lxc_console(struct lxc_container *c, int ttynum,
lxc_terminal_winsz
(
stdinfd
,
masterfd
);
lxc_terminal_winsz
(
stdinfd
,
masterfd
);
lxc_cmd_terminal_winch
(
ts
->
winch_proxy
,
ts
->
winch_proxy_lxcpath
);
lxc_cmd_terminal_winch
(
ts
->
winch_proxy
,
ts
->
winch_proxy_lxcpath
);
}
else
{
}
else
{
INFO
(
"File descriptor %d does not refer to a t
ty device
"
,
stdinfd
);
INFO
(
"File descriptor %d does not refer to a t
erminal
"
,
stdinfd
);
}
}
ret
=
lxc_mainloop_open
(
&
descr
);
ret
=
lxc_mainloop_open
(
&
descr
);
...
@@ -1097,7 +1131,7 @@ close_fds:
...
@@ -1097,7 +1131,7 @@ close_fds:
return
ret
;
return
ret
;
}
}
int
lxc_make_controlling_
pty
(
int
fd
)
int
lxc_make_controlling_
terminal
(
int
fd
)
{
{
int
ret
;
int
ret
;
...
@@ -1110,11 +1144,11 @@ int lxc_make_controlling_pty(int fd)
...
@@ -1110,11 +1144,11 @@ int lxc_make_controlling_pty(int fd)
return
0
;
return
0
;
}
}
int
lxc_
login_pty
(
int
fd
)
int
lxc_
terminal_prepare_login
(
int
fd
)
{
{
int
ret
;
int
ret
;
ret
=
lxc_make_controlling_
pty
(
fd
);
ret
=
lxc_make_controlling_
terminal
(
fd
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
-
1
;
return
-
1
;
...
@@ -1128,22 +1162,22 @@ int lxc_login_pty(int fd)
...
@@ -1128,22 +1162,22 @@ int lxc_login_pty(int fd)
return
0
;
return
0
;
}
}
void
lxc_terminal_info_init
(
struct
lxc_terminal_info
*
pty
)
void
lxc_terminal_info_init
(
struct
lxc_terminal_info
*
terminal
)
{
{
pty
->
name
[
0
]
=
'\0'
;
terminal
->
name
[
0
]
=
'\0'
;
pty
->
master
=
-
EBADF
;
terminal
->
master
=
-
EBADF
;
pty
->
slave
=
-
EBADF
;
terminal
->
slave
=
-
EBADF
;
pty
->
busy
=
-
1
;
terminal
->
busy
=
-
1
;
}
}
void
lxc_terminal_init
(
struct
lxc_terminal
*
pty
)
void
lxc_terminal_init
(
struct
lxc_terminal
*
terminal
)
{
{
memset
(
pty
,
0
,
sizeof
(
*
pty
));
memset
(
terminal
,
0
,
sizeof
(
*
terminal
));
pty
->
slave
=
-
EBADF
;
terminal
->
slave
=
-
EBADF
;
pty
->
master
=
-
EBADF
;
terminal
->
master
=
-
EBADF
;
pty
->
peer
=
-
EBADF
;
terminal
->
peer
=
-
EBADF
;
pty
->
log_fd
=
-
EBADF
;
terminal
->
log_fd
=
-
EBADF
;
lxc_terminal_info_init
(
&
pty
->
proxy
);
lxc_terminal_info_init
(
&
terminal
->
proxy
);
}
}
void
lxc_terminal_conf_free
(
struct
lxc_terminal
*
terminal
)
void
lxc_terminal_conf_free
(
struct
lxc_terminal
*
terminal
)
...
@@ -1154,24 +1188,23 @@ void lxc_terminal_conf_free(struct lxc_terminal *terminal)
...
@@ -1154,24 +1188,23 @@ void lxc_terminal_conf_free(struct lxc_terminal *terminal)
lxc_ringbuf_release
(
&
terminal
->
ringbuf
);
lxc_ringbuf_release
(
&
terminal
->
ringbuf
);
}
}
int
lxc_terminal_map_ids
(
struct
lxc_conf
*
c
,
struct
lxc_terminal
*
pty
)
int
lxc_terminal_map_ids
(
struct
lxc_conf
*
c
,
struct
lxc_terminal
*
terminal
)
{
{
int
ret
;
int
ret
;
if
(
lxc_list_empty
(
&
c
->
id_map
))
if
(
lxc_list_empty
(
&
c
->
id_map
))
return
0
;
return
0
;
ret
=
strcmp
(
pty
->
name
,
""
);
if
(
strcmp
(
terminal
->
name
,
""
)
==
0
)
if
(
ret
==
0
)
return
0
;
return
0
;
ret
=
chown_mapped_root
(
pty
->
name
,
c
);
ret
=
chown_mapped_root
(
terminal
->
name
,
c
);
if
(
ret
<
0
)
{
if
(
ret
<
0
)
{
ERROR
(
"Failed to chown
\"
%s
\"
"
,
pty
->
name
);
ERROR
(
"Failed to chown
terminal
\"
%s
\"
"
,
terminal
->
name
);
return
-
1
;
return
-
1
;
}
}
TRACE
(
"Chowned
\"
%s
\"
"
,
pty
->
name
);
TRACE
(
"Chowned
terminal
\"
%s
\"
"
,
terminal
->
name
);
return
0
;
return
0
;
}
}
src/lxc/terminal.h
View file @
ff305221
...
@@ -21,8 +21,8 @@
...
@@ -21,8 +21,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
*/
#ifndef __LXC_
CONSOLE
_H
#ifndef __LXC_
TERMINAL
_H
#define __LXC_
CONSOLE
_H
#define __LXC_
TERMINAL
_H
#include "config.h"
#include "config.h"
...
@@ -36,15 +36,17 @@ struct lxc_container;
...
@@ -36,15 +36,17 @@ struct lxc_container;
struct
lxc_conf
;
struct
lxc_conf
;
struct
lxc_epoll_descr
;
struct
lxc_epoll_descr
;
/* Defines a structure containing a pty information for virtualizing a tty
* @name : the path name of the slave pty side
* @master : the file descriptor of the master
* @slave : the file descriptor of the slave
*/
struct
lxc_terminal_info
{
struct
lxc_terminal_info
{
/* the path name of the slave side */
char
name
[
MAXPATHLEN
];
char
name
[
MAXPATHLEN
];
/* the file descriptor of the master */
int
master
;
int
master
;
/* the file descriptor of the slave */
int
slave
;
int
slave
;
/* whether the terminal is currently used */
int
busy
;
int
busy
;
};
};
...
@@ -53,25 +55,32 @@ struct lxc_terminal_state {
...
@@ -53,25 +55,32 @@ struct lxc_terminal_state {
int
stdinfd
;
int
stdinfd
;
int
stdoutfd
;
int
stdoutfd
;
int
masterfd
;
int
masterfd
;
/* Escape sequence to use for exiting the pty. A single char can be
* specified. The pty can then exited by doing: Ctrl + specified_char +
/* Escape sequence to use for exiting the terminal. A single char can
* q. This field is checked by lxc_terminal_stdin_cb(). Set to -1 to
* be specified. The terminal can then exited by doing: Ctrl +
* disable exiting the pty via a escape sequence.
* specified_char + q. This field is checked by
* lxc_terminal_stdin_cb(). Set to -1 to disable exiting the terminal
* via a escape sequence.
*/
*/
int
escape
;
int
escape
;
/* Used internally by lxc_terminal_stdin_cb() to check whether an
/* Used internally by lxc_terminal_stdin_cb() to check whether an
* escape sequence has been received.
* escape sequence has been received.
*/
*/
int
saw_escape
;
int
saw_escape
;
/* Name of the container to forward the SIGWINCH event to. */
/* Name of the container to forward the SIGWINCH event to. */
const
char
*
winch_proxy
;
const
char
*
winch_proxy
;
/* Path of the container to forward the SIGWINCH event to. */
/* Path of the container to forward the SIGWINCH event to. */
const
char
*
winch_proxy_lxcpath
;
const
char
*
winch_proxy_lxcpath
;
/* File descriptor that accepts signals. If set to -1 no signal handler
/* File descriptor that accepts signals. If set to -1 no signal handler
* could be installed. This also means that the sigset_t oldmask member
* could be installed. This also means that the sigset_t oldmask member
* is meaningless.
* is meaningless.
*/
*/
int
sigfd
;
int
sigfd
;
sigset_t
oldmask
;
sigset_t
oldmask
;
};
};
...
@@ -86,7 +95,7 @@ struct lxc_terminal {
...
@@ -86,7 +95,7 @@ struct lxc_terminal {
struct
termios
*
tios
;
struct
termios
*
tios
;
struct
lxc_terminal_state
*
tty_state
;
struct
lxc_terminal_state
*
tty_state
;
struct
/* lxc_
console
_log */
{
struct
/* lxc_
terminal
_log */
{
/* size of the log file */
/* size of the log file */
uint64_t
log_size
;
uint64_t
log_size
;
...
@@ -109,7 +118,7 @@ struct lxc_terminal {
...
@@ -109,7 +118,7 @@ struct lxc_terminal {
};
};
};
};
/*
/*
*
* lxc_terminal_allocate: allocate the console or a tty
* lxc_terminal_allocate: allocate the console or a tty
*
*
* @conf : the configuration of the container to allocate from
* @conf : the configuration of the container to allocate from
...
@@ -119,61 +128,54 @@ struct lxc_terminal {
...
@@ -119,61 +128,54 @@ struct lxc_terminal {
*/
*/
extern
int
lxc_terminal_allocate
(
struct
lxc_conf
*
conf
,
int
sockfd
,
int
*
ttynum
);
extern
int
lxc_terminal_allocate
(
struct
lxc_conf
*
conf
,
int
sockfd
,
int
*
ttynum
);
/*
/*
*
* Create a new
pty
:
* Create a new
terminal
:
* - calls openpty() to allocate a master/slave p
ty p
air
* - calls openpty() to allocate a master/slave pair
* - sets the FD_CLOEXEC flag on the master/slave fds
* - sets the FD_CLOEXEC flag on the master/slave fds
* - allocates either the current controlling
pty (default) or a user specified
* - allocates either the current controlling
terminal (default) or a user
*
pty as peer pt
y for the newly created master/slave pair
*
specified terminal as prox
y for the newly created master/slave pair
* - sets up SIGWINCH handler, winsz, and new terminal settings
* - sets up SIGWINCH handler, winsz, and new terminal settings
* (Handlers for SIGWINCH and I/O are not registered in a mainloop.)
* (Handlers for SIGWINCH and I/O are not registered in a mainloop.)
* (For an unprivileged container the created pty on the host is not
* automatically chowned to the uid/gid of the unprivileged user. For this
* ttys_shift_ids() can be called.)
*/
*/
extern
int
lxc_terminal_create
(
struct
lxc_terminal
*
console
);
extern
int
lxc_terminal_create
(
struct
lxc_terminal
*
console
);
/**
/**
* lxc_terminal_setup: Create a new
pty
.
* lxc_terminal_setup: Create a new
terminal
.
* - In addition to lxc_terminal_create() also sets up
all pty logs
.
* - In addition to lxc_terminal_create() also sets up
logging
.
*/
*/
extern
int
lxc_terminal_setup
(
struct
lxc_conf
*
);
extern
int
lxc_terminal_setup
(
struct
lxc_conf
*
);
/*
/**
* Delete a pty created via lxc_terminal_setup():
* Delete a terminal created via lxc_terminal_create() or lxc_terminal_setup():
* - set old terminal settings
* Note, registered handlers are not automatically deleted.
* - memory allocated via lxc_terminal_setup() is free()ed.
* - close master/slave pty pair and allocated fd for the peer (usually
* /dev/tty)
* Registered handlers in a mainloop are not automatically deleted.
*/
*/
extern
void
lxc_terminal_delete
(
struct
lxc_terminal
*
);
extern
void
lxc_terminal_delete
(
struct
lxc_terminal
*
);
/*
/*
*
* lxc_terminal_free: mark the
console or a tty as unallocated, free any
* lxc_terminal_free: mark the
terminal as unallocated and free any resources
*
resources
allocated by lxc_terminal_allocate().
* allocated by lxc_terminal_allocate().
*
*
* @conf : the configuration of the container whose tty was closed
* @conf : the configuration of the container whose tty was closed
* @fd : the socket fd whose remote side was closed, which indicated
* @fd : the socket fd whose remote side was closed, which indicated
* the
console or tty
is no longer in use. this is used to match
* the
terminal
is no longer in use. this is used to match
* which
console/tty
is being freed.
* which
terminal
is being freed.
*/
*/
extern
void
lxc_terminal_free
(
struct
lxc_conf
*
conf
,
int
fd
);
extern
void
lxc_terminal_free
(
struct
lxc_conf
*
conf
,
int
fd
);
/*
/*
*
* Register
pty event handlers in an open mainloop
* Register
terminal event handlers in an open mainloop.
*/
*/
extern
int
lxc_terminal_mainloop_add
(
struct
lxc_epoll_descr
*
,
struct
lxc_terminal
*
);
extern
int
lxc_terminal_mainloop_add
(
struct
lxc_epoll_descr
*
,
struct
lxc_terminal
*
);
/*
/*
*
* Handle SIGWINCH events on the allocated
pty
s.
* Handle SIGWINCH events on the allocated
terminal
s.
*/
*/
extern
void
lxc_terminal_sigwinch
(
int
sig
);
extern
void
lxc_terminal_sigwinch
(
int
sig
);
/*
/*
*
* Connect to one of the
p
tys given to the container via lxc.tty.max.
* Connect to one of the
t
tys given to the container via lxc.tty.max.
* - allocates either the current controlling
pty
(default) or a user specified
* - allocates either the current controlling
terminal
(default) or a user specified
*
pty as peer pty
for the containers tty
*
terminal as proxy terminal
for the containers tty
* - sets up SIGWINCH handler, winsz, and new terminal settings
* - sets up SIGWINCH handler, winsz, and new terminal settings
* - opens mainloop
* - opens mainloop
* - registers SIGWINCH, I/O handlers in the mainloop
* - registers SIGWINCH, I/O handlers in the mainloop
...
@@ -183,24 +185,24 @@ extern int lxc_console(struct lxc_container *c, int ttynum,
...
@@ -183,24 +185,24 @@ extern int lxc_console(struct lxc_container *c, int ttynum,
int
stdinfd
,
int
stdoutfd
,
int
stderrfd
,
int
stdinfd
,
int
stdoutfd
,
int
stderrfd
,
int
escape
);
int
escape
);
/*
/*
*
* Allocate one of the
ptys
given to the container via lxc.tty.max. Returns an
* Allocate one of the
tty
given to the container via lxc.tty.max. Returns an
* open fd to the allocated
p
ty.
* open fd to the allocated
t
ty.
* Set ttynum to -1 to allocate the first available
p
ty, or to a value within
* Set ttynum to -1 to allocate the first available
t
ty, or to a value within
* the range specified by lxc.tty.max to allocate a specific
p
ty.
* the range specified by lxc.tty.max to allocate a specific
t
ty.
*/
*/
extern
int
lxc_terminal_getfd
(
struct
lxc_container
*
c
,
int
*
ttynum
,
extern
int
lxc_terminal_getfd
(
struct
lxc_container
*
c
,
int
*
ttynum
,
int
*
masterfd
);
int
*
masterfd
);
/*
/*
*
* Make fd a duplicate of the standard file descriptors
:
* Make fd a duplicate of the standard file descriptors
. The fd is made a
*
fd is made a duplicate of a specific standard file descriptor iff th
e
*
duplicate of a specific standard file descriptor iff the standard fil
e
*
standard file descriptor refers to a pty
.
*
descriptor refers to a terminal
.
*/
*/
extern
int
lxc_terminal_set_stdfds
(
int
fd
);
extern
int
lxc_terminal_set_stdfds
(
int
fd
);
/*
/*
*
* Handler for events on the stdin fd of the
pty
. To be registered via the
* Handler for events on the stdin fd of the
terminal
. To be registered via the
* corresponding functions declared and defined in mainloop.{c,h} or
* corresponding functions declared and defined in mainloop.{c,h} or
* lxc_terminal_mainloop_add().
* lxc_terminal_mainloop_add().
* This function exits the loop cleanly when an EPOLLHUP event is received.
* This function exits the loop cleanly when an EPOLLHUP event is received.
...
@@ -208,42 +210,46 @@ extern int lxc_terminal_set_stdfds(int fd);
...
@@ -208,42 +210,46 @@ extern int lxc_terminal_set_stdfds(int fd);
extern
int
lxc_terminal_stdin_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
extern
int
lxc_terminal_stdin_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
);
struct
lxc_epoll_descr
*
descr
);
/*
/*
*
* Handler for events on the master fd of the
pty. To be registered via the
* Handler for events on the master fd of the
terminal. To be registered via
* corresponding functions declared and defined in mainloop.{c,h} or
*
the
corresponding functions declared and defined in mainloop.{c,h} or
* lxc_terminal_mainloop_add().
* lxc_terminal_mainloop_add().
* This function exits the loop cleanly when an EPOLLHUP event is received.
* This function exits the loop cleanly when an EPOLLHUP event is received.
*/
*/
extern
int
lxc_terminal_master_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
extern
int
lxc_terminal_master_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
);
struct
lxc_epoll_descr
*
descr
);
/*
/*
*
* Setup new terminal properties. The old terminal settings are stored in
* Setup new terminal properties. The old terminal settings are stored in
* oldtios.
* oldtios.
*/
*/
extern
int
lxc_setup_tios
(
int
fd
,
struct
termios
*
oldtios
);
extern
int
lxc_setup_tios
(
int
fd
,
struct
termios
*
oldtios
);
/*
/*
*
* lxc_terminal_winsz: propagate winsz from one terminal to another
* lxc_terminal_winsz: propagate winsz from one terminal to another
*
*
* @srcfd : terminal to get size from (typically a slave pty)
* @srcfd
* @dstfd : terminal to set size on (typically a master pty)
* - terminal to get size from (typically a slave pty)
* @dstfd
* - terminal to set size on (typically a master pty)
*/
*/
extern
void
lxc_terminal_winsz
(
int
srcfd
,
int
dstfd
);
extern
void
lxc_terminal_winsz
(
int
srcfd
,
int
dstfd
);
/*
/*
* lxc_terminal_signal_init: install signal handler
* lxc_terminal_signal_init: install signal handler
*
*
* @srcfd : src for winsz in SIGWINCH handler
* @srcfd
* @dstfd : dst for winsz in SIGWINCH handler
* - src for winsz in SIGWINCH handler
* @dstfd
* - dst for winsz in SIGWINCH handler
*
*
* Returns lxc_terminal_state structure on success or NULL on failure. The
sigfd
* Returns lxc_terminal_state structure on success or NULL on failure. The
*
member of the returned lxc_terminal_state can be select()/poll()ed/epoll()ed
*
sigfd member of the returned lxc_terminal_state can be
*
on (ie
added to a mainloop) for signals.
*
select()/poll()ed/epoll()ed on (i.e.
added to a mainloop) for signals.
*
*
* 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
*
from
a non-threaded context.
* a non-threaded context.
*
*
* Note that the signal handler isn't installed as a classic asychronous
* Note that the signal handler isn't installed as a classic asychronous
* handler, rather signalfd(2) is used so that we can handle the signal when
* handler, rather signalfd(2) is used so that we can handle the signal when
...
@@ -256,17 +262,18 @@ extern void lxc_terminal_winsz(int srcfd, int dstfd);
...
@@ -256,17 +262,18 @@ extern void lxc_terminal_winsz(int srcfd, int dstfd);
*/
*/
extern
struct
lxc_terminal_state
*
lxc_terminal_signal_init
(
int
srcfd
,
int
dstfd
);
extern
struct
lxc_terminal_state
*
lxc_terminal_signal_init
(
int
srcfd
,
int
dstfd
);
/*
/*
*
* Handler for signal events. To be registered via the corresponding functions
* Handler for signal events. To be registered via the corresponding functions
* declared and defined in mainloop.{c,h} or lxc_terminal_mainloop_add().
* declared and defined in mainloop.{c,h} or lxc_terminal_mainloop_add().
*/
*/
extern
int
lxc_terminal_signalfd_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
extern
int
lxc_terminal_signalfd_cb
(
int
fd
,
uint32_t
events
,
void
*
cbdata
,
struct
lxc_epoll_descr
*
descr
);
struct
lxc_epoll_descr
*
descr
);
/*
/*
*
* lxc_terminal_signal_fini: uninstall signal handler
* lxc_terminal_signal_fini: uninstall signal handler
*
*
* @ts : the lxc_terminal_state returned by lxc_terminal_signal_init
* @ts
* - the lxc_terminal_state returned by lxc_terminal_signal_init
*
*
* Restore the saved signal handler that was in effect at the time
* Restore the saved signal handler that was in effect at the time
* lxc_terminal_signal_init() was called.
* lxc_terminal_signal_init() was called.
...
@@ -276,16 +283,17 @@ extern int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata,
...
@@ -276,16 +283,17 @@ extern int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata,
*/
*/
extern
void
lxc_terminal_signal_fini
(
struct
lxc_terminal_state
*
ts
);
extern
void
lxc_terminal_signal_fini
(
struct
lxc_terminal_state
*
ts
);
extern
int
lxc_terminal_write_ringbuffer
(
struct
lxc_terminal
*
console
);
extern
int
lxc_terminal_write_ringbuffer
(
struct
lxc_terminal
*
terminal
);
extern
int
lxc_terminal_create_log_file
(
struct
lxc_terminal
*
console
);
extern
int
lxc_terminal_create_log_file
(
struct
lxc_terminal
*
terminal
);
extern
int
lxc_terminal_io_cb
(
int
fd
,
uint32_t
events
,
void
*
data
,
extern
int
lxc_terminal_io_cb
(
int
fd
,
uint32_t
events
,
void
*
data
,
struct
lxc_epoll_descr
*
descr
);
struct
lxc_epoll_descr
*
descr
);
extern
int
lxc_make_controlling_pty
(
int
fd
);
extern
int
lxc_make_controlling_terminal
(
int
fd
);
extern
int
lxc_login_pty
(
int
fd
);
extern
int
lxc_terminal_prepare_login
(
int
fd
);
extern
void
lxc_terminal_conf_free
(
struct
lxc_terminal
*
console
);
extern
void
lxc_terminal_conf_free
(
struct
lxc_terminal
*
terminal
);
extern
void
lxc_terminal_info_init
(
struct
lxc_terminal_info
*
pty
);
extern
void
lxc_terminal_info_init
(
struct
lxc_terminal_info
*
terminal
);
extern
void
lxc_terminal_init
(
struct
lxc_terminal
*
pty
);
extern
void
lxc_terminal_init
(
struct
lxc_terminal
*
terminal
);
extern
int
lxc_terminal_map_ids
(
struct
lxc_conf
*
c
,
struct
lxc_terminal
*
pty
);
extern
int
lxc_terminal_map_ids
(
struct
lxc_conf
*
c
,
struct
lxc_terminal
*
terminal
);
#endif
#endif
/* __LXC_TERMINAL_H */
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