]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/terminal.c
2 * lxc: linux Container library
4 * (C) Copyright IBM Corp. 2007, 2008
7 * Daniel Lezcano <daniel.lezcano at free.fr>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 #include <lxc/lxccontainer.h>
34 #include <sys/epoll.h>
35 #include <sys/types.h>
47 #include "memory_utils.h"
49 #include "syscall_wrappers.h"
56 #include <../include/openpty.h>
59 #define LXC_TERMINAL_BUFFER_SIZE 1024
61 lxc_log_define(terminal
, lxc
);
63 void lxc_terminal_winsz(int srcfd
, int dstfd
)
71 ret
= ioctl(srcfd
, TIOCGWINSZ
, &wsz
);
73 WARN("Failed to get window size");
77 ret
= ioctl(dstfd
, TIOCSWINSZ
, &wsz
);
79 WARN("Failed to set window size");
81 DEBUG("Set window size to %d columns and %d rows", wsz
.ws_col
,
87 static void lxc_terminal_winch(struct lxc_terminal_state
*ts
)
89 lxc_terminal_winsz(ts
->stdinfd
, ts
->masterfd
);
92 int lxc_terminal_signalfd_cb(int fd
, uint32_t events
, void *cbdata
,
93 struct lxc_epoll_descr
*descr
)
96 struct signalfd_siginfo siginfo
;
97 struct lxc_terminal_state
*ts
= cbdata
;
99 ret
= lxc_read_nointr(fd
, &siginfo
, sizeof(siginfo
));
100 if (ret
< 0 || (size_t)ret
< sizeof(siginfo
)) {
101 ERROR("Failed to read signal info");
102 return LXC_MAINLOOP_ERROR
;
105 if (siginfo
.ssi_signo
== SIGTERM
) {
106 DEBUG("Received SIGTERM. Detaching from the terminal");
107 return LXC_MAINLOOP_CLOSE
;
110 if (siginfo
.ssi_signo
== SIGWINCH
)
111 lxc_terminal_winch(ts
);
113 return LXC_MAINLOOP_CONTINUE
;
116 struct lxc_terminal_state
*lxc_terminal_signal_init(int srcfd
, int dstfd
)
118 __do_free
struct lxc_terminal_state
*ts
= NULL
;
123 ts
= malloc(sizeof(*ts
));
127 memset(ts
, 0, sizeof(*ts
));
129 ts
->masterfd
= dstfd
;
132 ret
= sigemptyset(&mask
);
134 SYSERROR("Failed to initialize an empty signal set");
138 istty
= (isatty(srcfd
) == 1);
140 INFO("fd %d does not refer to a tty device", srcfd
);
142 ret
= sigaddset(&mask
, SIGWINCH
);
144 SYSNOTICE("Failed to add SIGWINCH to signal set");
147 /* Exit the mainloop cleanly on SIGTERM. */
148 ret
= sigaddset(&mask
, SIGTERM
);
150 SYSERROR("Failed to add SIGWINCH to signal set");
154 ret
= pthread_sigmask(SIG_BLOCK
, &mask
, &ts
->oldmask
);
156 WARN("Failed to block signals");
160 ts
->sigfd
= signalfd(-1, &mask
, SFD_CLOEXEC
);
162 WARN("Failed to create signal fd");
163 (void)pthread_sigmask(SIG_SETMASK
, &ts
->oldmask
, NULL
);
167 DEBUG("Created signal fd %d", ts
->sigfd
);
171 ERROR("Failed to create signal fd");
172 if (ts
->sigfd
>= 0) {
180 void lxc_terminal_signal_fini(struct lxc_terminal
*terminal
)
182 struct lxc_terminal_state
*state
= terminal
->tty_state
;
184 if (!terminal
->tty_state
)
187 state
= terminal
->tty_state
;
188 if (state
->sigfd
>= 0) {
191 if (pthread_sigmask(SIG_SETMASK
, &state
->oldmask
, NULL
) < 0)
192 SYSWARN("Failed to restore signal mask");
195 free(terminal
->tty_state
);
196 terminal
->tty_state
= NULL
;
199 static int lxc_terminal_truncate_log_file(struct lxc_terminal
*terminal
)
201 /* be very certain things are kosher */
202 if (!terminal
->log_path
|| terminal
->log_fd
< 0)
205 return lxc_unpriv(ftruncate(terminal
->log_fd
, 0));
208 static int lxc_terminal_rotate_log_file(struct lxc_terminal
*terminal
)
210 __do_free
char *tmp
= NULL
;
214 if (!terminal
->log_path
|| terminal
->log_rotate
== 0)
217 /* be very certain things are kosher */
218 if (terminal
->log_fd
< 0)
221 len
= strlen(terminal
->log_path
) + sizeof(".1");
222 tmp
= must_realloc(NULL
, len
);
224 ret
= snprintf(tmp
, len
, "%s.1", terminal
->log_path
);
225 if (ret
< 0 || (size_t)ret
>= len
)
228 close(terminal
->log_fd
);
229 terminal
->log_fd
= -1;
230 ret
= lxc_unpriv(rename(terminal
->log_path
, tmp
));
234 return lxc_terminal_create_log_file(terminal
);
237 static int lxc_terminal_write_log_file(struct lxc_terminal
*terminal
, char *buf
,
242 int64_t space_left
= -1;
244 if (terminal
->log_fd
< 0)
247 /* A log size <= 0 means that there's no limit on the size of the log
248 * file at which point we simply ignore whether the log is supposed to
251 if (terminal
->log_size
<= 0)
252 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
254 /* Get current size of the log file. */
255 ret
= fstat(terminal
->log_fd
, &st
);
257 SYSERROR("Failed to stat the terminal log file descriptor");
261 /* handle non-regular files */
262 if ((st
.st_mode
& S_IFMT
) != S_IFREG
) {
263 /* This isn't a regular file. so rotating the file seems a
264 * dangerous thing to do, size limits are also very
265 * questionable. Let's not risk anything and tell the user that
266 * he's requesting us to do weird stuff.
268 if (terminal
->log_rotate
> 0 || terminal
->log_size
> 0)
271 /* I mean, sure log wherever you want to. */
272 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
275 space_left
= terminal
->log_size
- st
.st_size
;
277 /* User doesn't want to rotate the log file and there's no more space
278 * left so simply truncate it.
280 if (space_left
<= 0 && terminal
->log_rotate
<= 0) {
281 ret
= lxc_terminal_truncate_log_file(terminal
);
285 if (bytes_read
<= terminal
->log_size
)
286 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
288 /* Write as much as we can into the buffer and loose the rest. */
289 return lxc_write_nointr(terminal
->log_fd
, buf
, terminal
->log_size
);
292 /* There's enough space left. */
293 if (bytes_read
<= space_left
)
294 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
296 /* There's not enough space left but at least write as much as we can
297 * into the old log file.
299 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, space_left
);
303 /* Calculate how many bytes we still need to write. */
304 bytes_read
-= space_left
;
306 /* There'd be more to write but we aren't instructed to rotate the log
307 * file so simply return. There's no error on our side here.
309 if (terminal
->log_rotate
> 0)
310 ret
= lxc_terminal_rotate_log_file(terminal
);
312 ret
= lxc_terminal_truncate_log_file(terminal
);
316 if (terminal
->log_size
< bytes_read
) {
317 /* Well, this is unfortunate because it means that there is more
318 * to write than the user has granted us space. There are
319 * multiple ways to handle this but let's use the simplest one:
320 * write as much as we can, tell the user that there was more
321 * stuff to write and move on.
322 * Note that this scenario shouldn't actually happen with the
323 * standard pty-based terminal that LXC allocates since it will
324 * be switched into raw mode. In raw mode only 1 byte at a time
325 * should be read and written.
327 WARN("Size of terminal log file is smaller than the bytes to write");
328 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, terminal
->log_size
);
335 /* Yay, we made it. */
336 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
343 int lxc_terminal_io_cb(int fd
, uint32_t events
, void *data
,
344 struct lxc_epoll_descr
*descr
)
346 struct lxc_terminal
*terminal
= data
;
347 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
348 int r
, w
, w_log
, w_rbuf
;
350 w
= r
= lxc_read_nointr(fd
, buf
, sizeof(buf
));
352 INFO("Terminal client on fd %d has exited", fd
);
353 lxc_mainloop_del_handler(descr
, fd
);
355 if (fd
== terminal
->master
) {
356 terminal
->master
= -EBADF
;
357 } else if (fd
== terminal
->peer
) {
358 lxc_terminal_signal_fini(terminal
);
359 terminal
->peer
= -EBADF
;
361 ERROR("Handler received unexpected file descriptor");
365 return LXC_MAINLOOP_CLOSE
;
368 if (fd
== terminal
->peer
)
369 w
= lxc_write_nointr(terminal
->master
, buf
, r
);
372 if (fd
== terminal
->master
) {
373 /* write to peer first */
374 if (terminal
->peer
>= 0)
375 w
= lxc_write_nointr(terminal
->peer
, buf
, r
);
377 /* write to terminal ringbuffer */
378 if (terminal
->buffer_size
> 0)
379 w_rbuf
= lxc_ringbuf_write(&terminal
->ringbuf
, buf
, r
);
381 /* write to terminal log */
382 if (terminal
->log_fd
>= 0)
383 w_log
= lxc_terminal_write_log_file(terminal
, buf
, r
);
387 WARN("Short write on terminal r:%d != w:%d", r
, w
);
391 SYSTRACE("Failed to write %d bytes to terminal ringbuffer", r
);
395 TRACE("Failed to write %d bytes to terminal log", r
);
397 return LXC_MAINLOOP_CONTINUE
;
400 static int lxc_terminal_mainloop_add_peer(struct lxc_terminal
*terminal
)
404 if (terminal
->peer
>= 0) {
405 ret
= lxc_mainloop_add_handler(terminal
->descr
, terminal
->peer
,
406 lxc_terminal_io_cb
, terminal
);
408 WARN("Failed to add terminal peer handler to mainloop");
413 if (!terminal
->tty_state
|| terminal
->tty_state
->sigfd
< 0)
416 ret
= lxc_mainloop_add_handler(terminal
->descr
, terminal
->tty_state
->sigfd
,
417 lxc_terminal_signalfd_cb
, terminal
->tty_state
);
419 WARN("Failed to add signal handler to mainloop");
426 int lxc_terminal_mainloop_add(struct lxc_epoll_descr
*descr
,
427 struct lxc_terminal
*terminal
)
431 if (terminal
->master
< 0) {
432 INFO("Terminal is not initialized");
436 ret
= lxc_mainloop_add_handler(descr
, terminal
->master
,
437 lxc_terminal_io_cb
, terminal
);
439 ERROR("Failed to add handler for terminal master fd %d to "
440 "mainloop", terminal
->master
);
444 /* We cache the descr so that we can add an fd to it when someone
445 * does attach to it in lxc_terminal_allocate().
447 terminal
->descr
= descr
;
449 return lxc_terminal_mainloop_add_peer(terminal
);
452 int lxc_setup_tios(int fd
, struct termios
*oldtios
)
455 struct termios newtios
;
458 ERROR("File descriptor %d does not refer to a terminal", fd
);
462 /* Get current termios. */
463 ret
= tcgetattr(fd
, oldtios
);
465 SYSERROR("Failed to get current terminal settings");
469 /* ensure we don't end up in an endless loop:
470 * The kernel might fire SIGTTOU while an
471 * ioctl() in tcsetattr() is executed. When the ioctl()
472 * is resumed and retries, the signal handler interrupts it again.
474 signal (SIGTTIN
, SIG_IGN
);
475 signal (SIGTTOU
, SIG_IGN
);
479 /* We use the same settings that ssh does. */
480 newtios
.c_iflag
|= IGNPAR
;
481 newtios
.c_iflag
&= ~(ISTRIP
| INLCR
| IGNCR
| ICRNL
| IXON
| IXANY
| IXOFF
);
483 newtios
.c_iflag
&= ~IUCLC
;
485 newtios
.c_lflag
&= ~(TOSTOP
| ISIG
| ICANON
| ECHO
| ECHOE
| ECHOK
| ECHONL
);
487 newtios
.c_lflag
&= ~IEXTEN
;
489 newtios
.c_oflag
&= ~ONLCR
;
490 newtios
.c_oflag
|= OPOST
;
491 newtios
.c_cc
[VMIN
] = 1;
492 newtios
.c_cc
[VTIME
] = 0;
494 /* Set new attributes. */
495 ret
= tcsetattr(fd
, TCSAFLUSH
, &newtios
);
497 ERROR("Failed to set new terminal settings");
504 static void lxc_terminal_peer_proxy_free(struct lxc_terminal
*terminal
)
506 lxc_terminal_signal_fini(terminal
);
508 close(terminal
->proxy
.master
);
509 terminal
->proxy
.master
= -1;
511 close(terminal
->proxy
.slave
);
512 terminal
->proxy
.slave
= -1;
514 terminal
->proxy
.busy
= -1;
516 terminal
->proxy
.name
[0] = '\0';
521 static int lxc_terminal_peer_proxy_alloc(struct lxc_terminal
*terminal
,
525 struct termios oldtermio
;
526 struct lxc_terminal_state
*ts
;
528 if (terminal
->master
< 0) {
529 ERROR("Terminal not set up");
533 if (terminal
->proxy
.busy
!= -1 || terminal
->peer
!= -1) {
534 NOTICE("Terminal already in use");
538 if (terminal
->tty_state
) {
539 ERROR("Terminal has already been initialized");
543 /* This is the proxy terminal that will be given to the client, and
544 * that the real terminal master will send to / recv from.
546 ret
= openpty(&terminal
->proxy
.master
, &terminal
->proxy
.slave
, NULL
,
549 SYSERROR("Failed to open proxy terminal");
553 ret
= ttyname_r(terminal
->proxy
.slave
, terminal
->proxy
.name
,
554 sizeof(terminal
->proxy
.name
));
556 SYSERROR("Failed to retrieve name of proxy terminal slave");
560 ret
= fd_cloexec(terminal
->proxy
.master
, true);
562 SYSERROR("Failed to set FD_CLOEXEC flag on proxy terminal master");
566 ret
= fd_cloexec(terminal
->proxy
.slave
, true);
568 SYSERROR("Failed to set FD_CLOEXEC flag on proxy terminal slave");
572 ret
= lxc_setup_tios(terminal
->proxy
.slave
, &oldtermio
);
576 ts
= lxc_terminal_signal_init(terminal
->proxy
.master
, terminal
->master
);
580 terminal
->tty_state
= ts
;
581 terminal
->peer
= terminal
->proxy
.slave
;
582 terminal
->proxy
.busy
= sockfd
;
583 ret
= lxc_terminal_mainloop_add_peer(terminal
);
587 NOTICE("Opened proxy terminal with master fd %d and slave fd %d",
588 terminal
->proxy
.master
, terminal
->proxy
.slave
);
592 lxc_terminal_peer_proxy_free(terminal
);
596 int lxc_terminal_allocate(struct lxc_conf
*conf
, int sockfd
, int *ttyreq
)
600 struct lxc_tty_info
*ttys
= &conf
->ttys
;
601 struct lxc_terminal
*terminal
= &conf
->console
;
606 ret
= lxc_terminal_peer_proxy_alloc(terminal
, sockfd
);
610 masterfd
= terminal
->proxy
.master
;
615 if (*ttyreq
> ttys
->max
)
618 if (ttys
->tty
[*ttyreq
- 1].busy
)
621 /* The requested tty is available. */
626 /* Search for next available tty, fixup index tty1 => [0]. */
627 for (ttynum
= 1; ttynum
<= ttys
->max
&& ttys
->tty
[ttynum
- 1].busy
; ttynum
++) {
631 /* We didn't find any available slot for tty. */
632 if (ttynum
> ttys
->max
)
638 ttys
->tty
[ttynum
- 1].busy
= sockfd
;
639 masterfd
= ttys
->tty
[ttynum
- 1].master
;
645 void lxc_terminal_free(struct lxc_conf
*conf
, int fd
)
648 struct lxc_tty_info
*ttys
= &conf
->ttys
;
649 struct lxc_terminal
*terminal
= &conf
->console
;
651 for (i
= 0; i
< ttys
->max
; i
++)
652 if (ttys
->tty
[i
].busy
== fd
)
653 ttys
->tty
[i
].busy
= 0;
655 if (terminal
->proxy
.busy
!= fd
)
658 lxc_mainloop_del_handler(terminal
->descr
, terminal
->proxy
.slave
);
659 lxc_terminal_peer_proxy_free(terminal
);
662 static int lxc_terminal_peer_default(struct lxc_terminal
*terminal
)
664 struct lxc_terminal_state
*ts
;
669 path
= terminal
->path
;
673 terminal
->peer
= lxc_unpriv(open(path
, O_RDWR
| O_CLOEXEC
));
674 if (terminal
->peer
< 0) {
675 if (!terminal
->path
) {
677 SYSDEBUG("The process does not have a controlling terminal");
681 SYSERROR("Failed to open proxy terminal \"%s\"", path
);
684 DEBUG("Using terminal \"%s\" as proxy", path
);
686 if (!isatty(terminal
->peer
)) {
687 ERROR("File descriptor for \"%s\" does not refer to a terminal", path
);
688 goto on_error_free_tios
;
691 ts
= lxc_terminal_signal_init(terminal
->peer
, terminal
->master
);
692 terminal
->tty_state
= ts
;
694 WARN("Failed to install signal handler");
695 goto on_error_free_tios
;
698 lxc_terminal_winsz(terminal
->peer
, terminal
->master
);
700 terminal
->tios
= malloc(sizeof(*terminal
->tios
));
702 goto on_error_free_tios
;
704 ret
= lxc_setup_tios(terminal
->peer
, terminal
->tios
);
706 goto on_error_close_peer
;
711 free(terminal
->tios
);
712 terminal
->tios
= NULL
;
715 close(terminal
->peer
);
723 int lxc_terminal_write_ringbuffer(struct lxc_terminal
*terminal
)
728 struct lxc_ringbuf
*buf
= &terminal
->ringbuf
;
730 /* There's not log file where we can dump the ringbuffer to. */
731 if (terminal
->log_fd
< 0)
734 used
= lxc_ringbuf_used(buf
);
738 ret
= lxc_terminal_truncate_log_file(terminal
);
742 /* Write as much as we can without exceeding the limit. */
743 if (terminal
->log_size
< used
)
744 used
= terminal
->log_size
;
746 r_addr
= lxc_ringbuf_get_read_addr(buf
);
747 ret
= lxc_write_nointr(terminal
->log_fd
, r_addr
, used
);
754 void lxc_terminal_delete(struct lxc_terminal
*terminal
)
758 ret
= lxc_terminal_write_ringbuffer(terminal
);
760 WARN("Failed to write terminal log to disk");
762 if (terminal
->tios
&& terminal
->peer
>= 0) {
763 ret
= tcsetattr(terminal
->peer
, TCSAFLUSH
, terminal
->tios
);
765 SYSWARN("Failed to set old terminal settings");
767 free(terminal
->tios
);
768 terminal
->tios
= NULL
;
770 if (terminal
->peer
>= 0)
771 close(terminal
->peer
);
774 if (terminal
->master
>= 0)
775 close(terminal
->master
);
776 terminal
->master
= -1;
778 if (terminal
->slave
>= 0)
779 close(terminal
->slave
);
780 terminal
->slave
= -1;
782 if (terminal
->log_fd
>= 0)
783 close(terminal
->log_fd
);
784 terminal
->log_fd
= -1;
788 * Note that this function needs to run before the mainloop starts. Since we
789 * register a handler for the terminal's masterfd when we create the mainloop
790 * the terminal handler needs to see an allocated ringbuffer.
792 static int lxc_terminal_create_ringbuf(struct lxc_terminal
*terminal
)
795 struct lxc_ringbuf
*buf
= &terminal
->ringbuf
;
796 uint64_t size
= terminal
->buffer_size
;
798 /* no ringbuffer previously allocated and no ringbuffer requested */
799 if (!buf
->addr
&& size
<= 0)
802 /* ringbuffer allocated but no new ringbuffer requested */
803 if (buf
->addr
&& size
<= 0) {
804 lxc_ringbuf_release(buf
);
809 TRACE("Deallocated terminal ringbuffer");
816 /* check wether the requested size for the ringbuffer has changed */
817 if (buf
->addr
&& buf
->size
!= size
) {
818 TRACE("Terminal ringbuffer size changed from %" PRIu64
819 " to %" PRIu64
" bytes. Deallocating terminal ringbuffer",
821 lxc_ringbuf_release(buf
);
824 ret
= lxc_ringbuf_create(buf
, size
);
826 ERROR("Failed to setup %" PRIu64
" byte terminal ringbuffer", size
);
830 TRACE("Allocated %" PRIu64
" byte terminal ringbuffer", size
);
835 * This is the terminal log file. Please note that the terminal log file is
836 * (implementation wise not content wise) independent of the terminal ringbuffer.
838 int lxc_terminal_create_log_file(struct lxc_terminal
*terminal
)
840 if (!terminal
->log_path
)
843 terminal
->log_fd
= lxc_unpriv(open(terminal
->log_path
, O_CLOEXEC
| O_RDWR
| O_CREAT
| O_APPEND
, 0600));
844 if (terminal
->log_fd
< 0) {
845 SYSERROR("Failed to open terminal log file \"%s\"", terminal
->log_path
);
849 DEBUG("Using \"%s\" as terminal log file", terminal
->log_path
);
853 int lxc_terminal_create(struct lxc_terminal
*terminal
)
857 ret
= openpty(&terminal
->master
, &terminal
->slave
, NULL
, NULL
, NULL
);
859 SYSERROR("Failed to open terminal");
863 ret
= ttyname_r(terminal
->slave
, terminal
->name
, sizeof(terminal
->name
));
865 SYSERROR("Failed to retrieve name of terminal slave");
869 ret
= fd_cloexec(terminal
->master
, true);
871 SYSERROR("Failed to set FD_CLOEXEC flag on terminal master");
875 ret
= fd_cloexec(terminal
->slave
, true);
877 SYSERROR("Failed to set FD_CLOEXEC flag on terminal slave");
881 ret
= lxc_terminal_peer_default(terminal
);
883 ERROR("Failed to allocate proxy terminal");
890 lxc_terminal_delete(terminal
);
894 int lxc_terminal_setup(struct lxc_conf
*conf
)
897 struct lxc_terminal
*terminal
= &conf
->console
;
899 if (terminal
->path
&& strcmp(terminal
->path
, "none") == 0) {
900 INFO("No terminal requested");
904 ret
= lxc_terminal_create(terminal
);
908 ret
= lxc_terminal_create_log_file(terminal
);
912 ret
= lxc_terminal_create_ringbuf(terminal
);
919 lxc_terminal_delete(terminal
);
923 static bool __terminal_dup2(int duplicate
, int original
)
927 if (!isatty(original
))
930 ret
= dup2(duplicate
, original
);
932 SYSERROR("Failed to dup2(%d, %d)", duplicate
, original
);
939 int lxc_terminal_set_stdfds(int fd
)
946 for (i
= 0; i
< 3; i
++)
947 if (!__terminal_dup2(fd
, (int[]){STDIN_FILENO
, STDOUT_FILENO
,
954 int lxc_terminal_stdin_cb(int fd
, uint32_t events
, void *cbdata
,
955 struct lxc_epoll_descr
*descr
)
959 struct lxc_terminal_state
*ts
= cbdata
;
961 if (fd
!= ts
->stdinfd
)
962 return LXC_MAINLOOP_CLOSE
;
964 ret
= lxc_read_nointr(ts
->stdinfd
, &c
, 1);
966 return LXC_MAINLOOP_CLOSE
;
968 if (ts
->escape
>= 1) {
969 /* we want to exit the terminal with Ctrl+a q */
970 if (c
== ts
->escape
&& !ts
->saw_escape
) {
972 return LXC_MAINLOOP_CONTINUE
;
975 if (c
== 'q' && ts
->saw_escape
)
976 return LXC_MAINLOOP_CLOSE
;
981 ret
= lxc_write_nointr(ts
->masterfd
, &c
, 1);
983 return LXC_MAINLOOP_CLOSE
;
985 return LXC_MAINLOOP_CONTINUE
;
988 int lxc_terminal_master_cb(int fd
, uint32_t events
, void *cbdata
,
989 struct lxc_epoll_descr
*descr
)
992 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
993 struct lxc_terminal_state
*ts
= cbdata
;
995 if (fd
!= ts
->masterfd
)
996 return LXC_MAINLOOP_CLOSE
;
998 r
= lxc_read_nointr(fd
, buf
, sizeof(buf
));
1000 return LXC_MAINLOOP_CLOSE
;
1002 w
= lxc_write_nointr(ts
->stdoutfd
, buf
, r
);
1003 if (w
<= 0 || w
!= r
)
1004 return LXC_MAINLOOP_CLOSE
;
1006 return LXC_MAINLOOP_CONTINUE
;
1009 int lxc_terminal_getfd(struct lxc_container
*c
, int *ttynum
, int *masterfd
)
1011 return lxc_cmd_console(c
->name
, ttynum
, masterfd
, c
->config_path
);
1014 int lxc_console(struct lxc_container
*c
, int ttynum
,
1015 int stdinfd
, int stdoutfd
, int stderrfd
,
1018 int masterfd
, ret
, ttyfd
;
1019 struct lxc_epoll_descr descr
;
1020 struct termios oldtios
;
1021 struct lxc_terminal_state
*ts
;
1022 struct lxc_terminal terminal
= {
1027 ttyfd
= lxc_cmd_console(c
->name
, &ttynum
, &masterfd
, c
->config_path
);
1033 TRACE("Process is already group leader");
1035 ts
= lxc_terminal_signal_init(stdinfd
, masterfd
);
1040 terminal
.tty_state
= ts
;
1041 ts
->escape
= escape
;
1042 ts
->stdoutfd
= stdoutfd
;
1044 istty
= isatty(stdinfd
);
1046 lxc_terminal_winsz(stdinfd
, masterfd
);
1047 lxc_terminal_winsz(ts
->stdinfd
, ts
->masterfd
);
1049 INFO("File descriptor %d does not refer to a terminal", stdinfd
);
1052 ret
= lxc_mainloop_open(&descr
);
1054 ERROR("Failed to create mainloop");
1058 if (ts
->sigfd
!= -1) {
1059 ret
= lxc_mainloop_add_handler(&descr
, ts
->sigfd
,
1060 lxc_terminal_signalfd_cb
, ts
);
1062 ERROR("Failed to add signal handler to mainloop");
1063 goto close_mainloop
;
1067 ret
= lxc_mainloop_add_handler(&descr
, ts
->stdinfd
,
1068 lxc_terminal_stdin_cb
, ts
);
1070 ERROR("Failed to add stdin handler");
1071 goto close_mainloop
;
1074 ret
= lxc_mainloop_add_handler(&descr
, ts
->masterfd
,
1075 lxc_terminal_master_cb
, ts
);
1077 ERROR("Failed to add master handler");
1078 goto close_mainloop
;
1081 if (ts
->escape
>= 1) {
1084 "Connected to tty %1$d\n"
1085 "Type <Ctrl+%2$c q> to exit the console, "
1086 "<Ctrl+%2$c Ctrl+%2$c> to enter Ctrl+%2$c itself\n",
1087 ttynum
, 'a' + escape
- 1);
1091 ret
= lxc_setup_tios(stdinfd
, &oldtios
);
1093 goto close_mainloop
;
1096 ret
= lxc_mainloop(&descr
, -1);
1098 ERROR("The mainloop returned an error");
1106 istty
= tcsetattr(stdinfd
, TCSAFLUSH
, &oldtios
);
1108 SYSWARN("Failed to restore terminal properties");
1112 lxc_mainloop_close(&descr
);
1115 lxc_terminal_signal_fini(&terminal
);
1124 int lxc_make_controlling_terminal(int fd
)
1130 ret
= ioctl(fd
, TIOCSCTTY
, (char *)NULL
);
1137 int lxc_terminal_prepare_login(int fd
)
1141 ret
= lxc_make_controlling_terminal(fd
);
1145 ret
= lxc_terminal_set_stdfds(fd
);
1149 if (fd
> STDERR_FILENO
)
1155 void lxc_terminal_info_init(struct lxc_terminal_info
*terminal
)
1157 terminal
->name
[0] = '\0';
1158 terminal
->master
= -EBADF
;
1159 terminal
->slave
= -EBADF
;
1160 terminal
->busy
= -1;
1163 void lxc_terminal_init(struct lxc_terminal
*terminal
)
1165 memset(terminal
, 0, sizeof(*terminal
));
1166 terminal
->slave
= -EBADF
;
1167 terminal
->master
= -EBADF
;
1168 terminal
->peer
= -EBADF
;
1169 terminal
->log_fd
= -EBADF
;
1170 lxc_terminal_info_init(&terminal
->proxy
);
1173 void lxc_terminal_conf_free(struct lxc_terminal
*terminal
)
1175 free(terminal
->log_path
);
1176 free(terminal
->path
);
1177 if (terminal
->buffer_size
> 0 && terminal
->ringbuf
.addr
)
1178 lxc_ringbuf_release(&terminal
->ringbuf
);
1179 lxc_terminal_signal_fini(terminal
);
1182 int lxc_terminal_map_ids(struct lxc_conf
*c
, struct lxc_terminal
*terminal
)
1186 if (lxc_list_empty(&c
->id_map
))
1189 if (strcmp(terminal
->name
, "") == 0)
1192 ret
= chown_mapped_root(terminal
->name
, c
);
1194 ERROR("Failed to chown terminal \"%s\"", terminal
->name
);
1198 TRACE("Chowned terminal \"%s\"", terminal
->name
);