]>
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
31 #include <sys/epoll.h>
32 #include <sys/types.h>
34 #include <lxc/lxccontainer.h>
44 #include "start.h" /* for struct lxc_handler */
51 #include <../include/openpty.h>
54 #define LXC_TERMINAL_BUFFER_SIZE 1024
56 lxc_log_define(terminal
, lxc
);
58 static struct lxc_list lxc_ttys
;
60 typedef void (*sighandler_t
)(int);
62 __attribute__((constructor
)) void lxc_terminal_init_global(void)
64 lxc_list_init(&lxc_ttys
);
67 void lxc_terminal_winsz(int srcfd
, int dstfd
)
75 ret
= ioctl(srcfd
, TIOCGWINSZ
, &wsz
);
77 WARN("Failed to get window size");
81 ret
= ioctl(dstfd
, TIOCSWINSZ
, &wsz
);
83 WARN("Failed to set window size");
85 DEBUG("Set window size to %d columns and %d rows", wsz
.ws_col
,
91 static void lxc_terminal_winch(struct lxc_terminal_state
*ts
)
93 lxc_terminal_winsz(ts
->stdinfd
, ts
->masterfd
);
96 lxc_cmd_terminal_winch(ts
->winch_proxy
, ts
->winch_proxy_lxcpath
);
99 void lxc_terminal_sigwinch(int sig
)
102 struct lxc_terminal_state
*ts
;
104 lxc_list_for_each(it
, &lxc_ttys
) {
106 lxc_terminal_winch(ts
);
110 int lxc_terminal_signalfd_cb(int fd
, uint32_t events
, void *cbdata
,
111 struct lxc_epoll_descr
*descr
)
114 struct signalfd_siginfo siginfo
;
115 struct lxc_terminal_state
*ts
= cbdata
;
117 ret
= read(fd
, &siginfo
, sizeof(siginfo
));
118 if (ret
< 0 || (size_t)ret
< sizeof(siginfo
)) {
119 ERROR("Failed to read signal info");
123 if (siginfo
.ssi_signo
== SIGTERM
) {
124 DEBUG("Received SIGTERM. Detaching from the terminal");
125 return LXC_MAINLOOP_CLOSE
;
128 if (siginfo
.ssi_signo
== SIGWINCH
)
129 lxc_terminal_winch(ts
);
134 struct lxc_terminal_state
*lxc_terminal_signal_init(int srcfd
, int dstfd
)
139 struct lxc_terminal_state
*ts
;
141 ts
= malloc(sizeof(*ts
));
145 memset(ts
, 0, sizeof(*ts
));
147 ts
->masterfd
= dstfd
;
152 istty
= isatty(srcfd
) == 1;
154 INFO("fd %d does not refer to a tty device", srcfd
);
156 /* Add tty to list to be scanned at SIGWINCH time. */
157 lxc_list_add_elem(&ts
->node
, ts
);
158 lxc_list_add_tail(&lxc_ttys
, &ts
->node
);
159 sigaddset(&mask
, SIGWINCH
);
162 /* Exit the mainloop cleanly on SIGTERM. */
163 sigaddset(&mask
, SIGTERM
);
165 ret
= sigprocmask(SIG_BLOCK
, &mask
, &ts
->oldmask
);
167 WARN("Failed to block signals");
171 ts
->sigfd
= signalfd(-1, &mask
, SFD_CLOEXEC
);
173 WARN("Failed to create signal fd");
174 sigprocmask(SIG_SETMASK
, &ts
->oldmask
, NULL
);
178 DEBUG("Created signal fd %d", ts
->sigfd
);
182 ERROR("Failed to create signal fd");
183 if (ts
->sigfd
>= 0) {
188 lxc_list_del(&ts
->node
);
192 void lxc_terminal_signal_fini(struct lxc_terminal_state
*ts
)
194 if (ts
->sigfd
>= 0) {
197 if (sigprocmask(SIG_SETMASK
, &ts
->oldmask
, NULL
) < 0)
198 WARN("%s - Failed to restore signal mask", strerror(errno
));
201 if (isatty(ts
->stdinfd
))
202 lxc_list_del(&ts
->node
);
207 static int lxc_terminal_truncate_log_file(struct lxc_terminal
*terminal
)
209 /* be very certain things are kosher */
210 if (!terminal
->log_path
|| terminal
->log_fd
< 0)
213 return lxc_unpriv(ftruncate(terminal
->log_fd
, 0));
216 static int lxc_console_rotate_log_file(struct lxc_terminal
*terminal
)
222 if (!terminal
->log_path
|| terminal
->log_rotate
== 0)
225 /* be very certain things are kosher */
226 if (terminal
->log_fd
< 0)
229 len
= strlen(terminal
->log_path
) + sizeof(".1");
232 ret
= snprintf(tmp
, len
, "%s.1", terminal
->log_path
);
233 if (ret
< 0 || (size_t)ret
>= len
)
236 close(terminal
->log_fd
);
237 terminal
->log_fd
= -1;
238 ret
= lxc_unpriv(rename(terminal
->log_path
, tmp
));
242 return lxc_terminal_create_log_file(terminal
);
245 static int lxc_console_write_log_file(struct lxc_terminal
*terminal
, char *buf
,
249 int64_t space_left
= -1;
252 if (terminal
->log_fd
< 0)
255 /* A log size <= 0 means that there's no limit on the size of the log
256 * file at which point we simply ignore whether the log is supposed to
259 if (terminal
->log_size
<= 0)
260 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
262 /* Get current size of the log file. */
263 ret
= fstat(terminal
->log_fd
, &st
);
265 SYSERROR("Failed to stat the terminal log file descriptor");
269 /* handle non-regular files */
270 if ((st
.st_mode
& S_IFMT
) != S_IFREG
) {
271 /* This isn't a regular file. so rotating the file seems a
272 * dangerous thing to do, size limits are also very
273 * questionable. Let's not risk anything and tell the user that
274 * he's requesting us to do weird stuff.
276 if (terminal
->log_rotate
> 0 || terminal
->log_size
> 0)
279 /* I mean, sure log wherever you want to. */
280 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
283 space_left
= terminal
->log_size
- st
.st_size
;
285 /* User doesn't want to rotate the log file and there's no more space
286 * left so simply truncate it.
288 if (space_left
<= 0 && terminal
->log_rotate
<= 0) {
289 ret
= lxc_terminal_truncate_log_file(terminal
);
293 if (bytes_read
<= terminal
->log_size
)
294 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
296 /* Write as much as we can into the buffer and loose the rest. */
297 return lxc_write_nointr(terminal
->log_fd
, buf
, terminal
->log_size
);
300 /* There's enough space left. */
301 if (bytes_read
<= space_left
)
302 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
304 /* There's not enough space left but at least write as much as we can
305 * into the old log file.
307 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, space_left
);
311 /* Calculate how many bytes we still need to write. */
312 bytes_read
-= space_left
;
314 /* There'd be more to write but we aren't instructed to rotate the log
315 * file so simply return. There's no error on our side here.
317 if (terminal
->log_rotate
> 0)
318 ret
= lxc_console_rotate_log_file(terminal
);
320 ret
= lxc_terminal_truncate_log_file(terminal
);
324 if (terminal
->log_size
< bytes_read
) {
325 /* Well, this is unfortunate because it means that there is more
326 * to write than the user has granted us space. There are
327 * multiple ways to handle this but let's use the simplest one:
328 * write as much as we can, tell the user that there was more
329 * stuff to write and move on.
330 * Note that this scenario shouldn't actually happen with the
331 * standard pty-based terminal that LXC allocates since it will
332 * be switched into raw mode. In raw mode only 1 byte at a time
333 * should be read and written.
335 WARN("Size of terminal log file is smaller than the bytes to write");
336 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, terminal
->log_size
);
343 /* Yay, we made it. */
344 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
351 int lxc_terminal_io_cb(int fd
, uint32_t events
, void *data
,
352 struct lxc_epoll_descr
*descr
)
354 struct lxc_terminal
*terminal
= data
;
355 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
356 int r
, w
, w_log
, w_rbuf
;
358 w
= r
= lxc_read_nointr(fd
, buf
, sizeof(buf
));
360 INFO("Terminal client on fd %d has exited", fd
);
361 lxc_mainloop_del_handler(descr
, fd
);
363 if (fd
== terminal
->master
) {
364 terminal
->master
= -EBADF
;
365 } else if (fd
== terminal
->peer
) {
366 if (terminal
->tty_state
) {
367 lxc_terminal_signal_fini(terminal
->tty_state
);
368 terminal
->tty_state
= NULL
;
370 terminal
->peer
= -EBADF
;
372 ERROR("Handler received unexpected file descriptor");
376 return LXC_MAINLOOP_CLOSE
;
379 if (fd
== terminal
->peer
)
380 w
= lxc_write_nointr(terminal
->master
, buf
, r
);
383 if (fd
== terminal
->master
) {
384 /* write to peer first */
385 if (terminal
->peer
>= 0)
386 w
= lxc_write_nointr(terminal
->peer
, buf
, r
);
388 /* write to terminal ringbuffer */
389 if (terminal
->buffer_size
> 0)
390 w_rbuf
= lxc_ringbuf_write(&terminal
->ringbuf
, buf
, r
);
392 /* write to terminal log */
393 if (terminal
->log_fd
>= 0)
394 w_log
= lxc_console_write_log_file(terminal
, buf
, r
);
398 WARN("Short write on terminal r:%d != w:%d", r
, w
);
401 TRACE("%s - Failed to write %d bytes to terminal ringbuffer",
402 strerror(-w_rbuf
), r
);
405 TRACE("Failed to write %d bytes to terminal log", r
);
410 static int lxc_terminal_mainloop_add_peer(struct lxc_terminal
*terminal
)
414 if (terminal
->peer
>= 0) {
415 ret
= lxc_mainloop_add_handler(terminal
->descr
, terminal
->peer
,
416 lxc_terminal_io_cb
, terminal
);
418 WARN("Failed to add terminal peer handler to mainloop");
423 if (!terminal
->tty_state
|| terminal
->tty_state
->sigfd
< 0)
426 ret
= lxc_mainloop_add_handler(terminal
->descr
, terminal
->tty_state
->sigfd
,
427 lxc_terminal_signalfd_cb
, terminal
->tty_state
);
429 WARN("Failed to add signal handler to mainloop");
436 int lxc_terminal_mainloop_add(struct lxc_epoll_descr
*descr
,
437 struct lxc_terminal
*terminal
)
441 if (terminal
->master
< 0) {
442 INFO("Terminal is not initialized");
446 ret
= lxc_mainloop_add_handler(descr
, terminal
->master
,
447 lxc_terminal_io_cb
, terminal
);
449 ERROR("Failed to add handler for %d to mainloop", terminal
->master
);
453 /* We cache the descr so that we can add an fd to it when someone
454 * does attach to it in lxc_terminal_allocate().
456 terminal
->descr
= descr
;
457 ret
= lxc_terminal_mainloop_add_peer(terminal
);
464 int lxc_setup_tios(int fd
, struct termios
*oldtios
)
466 struct termios newtios
;
469 ERROR("'%d' is not a tty", fd
);
473 /* Get current termios */
474 if (tcgetattr(fd
, oldtios
)) {
475 SYSERROR("failed to get current terminal settings");
479 /* ensure we don't end up in an endless loop:
480 * The kernel might fire SIGTTOU while an
481 * ioctl() in tcsetattr() is executed. When the ioctl()
482 * is resumed and retries, the signal handler interrupts it again.
484 signal (SIGTTIN
, SIG_IGN
);
485 signal (SIGTTOU
, SIG_IGN
);
489 /* We use the same settings that ssh does. */
490 newtios
.c_iflag
|= IGNPAR
;
491 newtios
.c_iflag
&= ~(ISTRIP
| INLCR
| IGNCR
| ICRNL
| IXON
| IXANY
| IXOFF
);
493 newtios
.c_iflag
&= ~IUCLC
;
495 newtios
.c_lflag
&= ~(TOSTOP
| ISIG
| ICANON
| ECHO
| ECHOE
| ECHOK
| ECHONL
);
497 newtios
.c_lflag
&= ~IEXTEN
;
499 newtios
.c_oflag
&= ~OPOST
;
500 newtios
.c_cc
[VMIN
] = 1;
501 newtios
.c_cc
[VTIME
] = 0;
503 /* Set new attributes. */
504 if (tcsetattr(fd
, TCSAFLUSH
, &newtios
)) {
505 ERROR("failed to set new terminal settings");
512 static void lxc_terminal_peer_proxy_free(struct lxc_terminal
*terminal
)
514 if (terminal
->tty_state
) {
515 lxc_terminal_signal_fini(terminal
->tty_state
);
516 terminal
->tty_state
= NULL
;
518 close(terminal
->peerpty
.master
);
519 close(terminal
->peerpty
.slave
);
520 terminal
->peerpty
.master
= -1;
521 terminal
->peerpty
.slave
= -1;
522 terminal
->peerpty
.busy
= -1;
523 terminal
->peerpty
.name
[0] = '\0';
527 static int lxc_terminal_peer_proxy_alloc(struct lxc_terminal
*terminal
, int sockfd
)
529 struct termios oldtermio
;
530 struct lxc_terminal_state
*ts
;
533 if (terminal
->master
< 0) {
534 ERROR("Terminal not set up");
537 if (terminal
->peerpty
.busy
!= -1 || terminal
->peer
!= -1) {
538 NOTICE("Terminal already in use");
541 if (terminal
->tty_state
) {
542 ERROR("Terminal already has tty_state");
546 /* this is the proxy pty that will be given to the client, and that
547 * the real pty master will send to / recv from
549 ret
= openpty(&terminal
->peerpty
.master
, &terminal
->peerpty
.slave
,
550 terminal
->peerpty
.name
, NULL
, NULL
);
552 SYSERROR("failed to create proxy pty");
556 if (lxc_setup_tios(terminal
->peerpty
.slave
, &oldtermio
) < 0)
559 ts
= lxc_terminal_signal_init(terminal
->peerpty
.master
, terminal
->master
);
563 terminal
->tty_state
= ts
;
564 terminal
->peer
= terminal
->peerpty
.slave
;
565 terminal
->peerpty
.busy
= sockfd
;
566 ret
= lxc_terminal_mainloop_add_peer(terminal
);
570 DEBUG("%d peermaster:%d sockfd:%d", lxc_raw_getpid(), terminal
->peerpty
.master
, sockfd
);
574 lxc_terminal_peer_proxy_free(terminal
);
578 int lxc_terminal_allocate(struct lxc_conf
*conf
, int sockfd
, int *ttyreq
)
580 int masterfd
= -1, ttynum
;
581 struct lxc_tty_info
*ttys
= &conf
->ttys
;
582 struct lxc_terminal
*terminal
= &conf
->console
;
585 if (lxc_terminal_peer_proxy_alloc(terminal
, sockfd
) < 0)
587 masterfd
= terminal
->peerpty
.master
;
592 if (*ttyreq
> ttys
->nbtty
)
595 if (ttys
->tty
[*ttyreq
- 1].busy
)
598 /* the requested tty is available */
603 /* search for next available tty, fixup index tty1 => [0] */
604 for (ttynum
= 1; ttynum
<= ttys
->nbtty
&& ttys
->tty
[ttynum
- 1].busy
; ttynum
++)
607 /* we didn't find any available slot for tty */
608 if (ttynum
> ttys
->nbtty
)
614 ttys
->tty
[ttynum
- 1].busy
= sockfd
;
615 masterfd
= ttys
->tty
[ttynum
- 1].master
;
620 void lxc_terminal_free(struct lxc_conf
*conf
, int fd
)
623 struct lxc_tty_info
*ttys
= &conf
->ttys
;
624 struct lxc_terminal
*terminal
= &conf
->console
;
626 for (i
= 0; i
< ttys
->nbtty
; i
++) {
627 if (ttys
->tty
[i
].busy
== fd
)
628 ttys
->tty
[i
].busy
= 0;
631 if (terminal
->peerpty
.busy
== fd
) {
632 lxc_mainloop_del_handler(terminal
->descr
, terminal
->peerpty
.slave
);
633 lxc_terminal_peer_proxy_free(terminal
);
637 static int lxc_terminal_peer_default(struct lxc_terminal
*terminal
)
639 struct lxc_terminal_state
*ts
;
640 const char *path
= terminal
->path
;
644 /* If no terminal was given, try current controlling terminal, there
645 * won't be one if we were started as a daemon (-d).
647 if (!path
&& !access("/dev/tty", F_OK
)) {
648 fd
= open("/dev/tty", O_RDWR
);
657 DEBUG("process does not have a controlling terminal");
661 terminal
->peer
= lxc_unpriv(open(path
, O_RDWR
| O_CLOEXEC
));
662 if (terminal
->peer
< 0) {
663 ERROR("Failed to open \"%s\": %s", path
, strerror(errno
));
666 DEBUG("using \"%s\" as peer tty device", path
);
668 if (!isatty(terminal
->peer
)) {
669 ERROR("file descriptor for file \"%s\" does not refer to a tty device", path
);
673 ts
= lxc_terminal_signal_init(terminal
->peer
, terminal
->master
);
674 terminal
->tty_state
= ts
;
676 WARN("Failed to install signal handler");
680 lxc_terminal_winsz(terminal
->peer
, terminal
->master
);
682 terminal
->tios
= malloc(sizeof(*terminal
->tios
));
683 if (!terminal
->tios
) {
684 SYSERROR("failed to allocate memory");
688 if (lxc_setup_tios(terminal
->peer
, terminal
->tios
) < 0)
694 free(terminal
->tios
);
695 terminal
->tios
= NULL
;
698 close(terminal
->peer
);
706 int lxc_terminal_write_ringbuffer(struct lxc_terminal
*terminal
)
711 struct lxc_ringbuf
*buf
= &terminal
->ringbuf
;
713 /* There's not log file where we can dump the ringbuffer to. */
714 if (terminal
->log_fd
< 0)
717 used
= lxc_ringbuf_used(buf
);
721 ret
= lxc_terminal_truncate_log_file(terminal
);
725 /* Write as much as we can without exceeding the limit. */
726 if (terminal
->log_size
< used
)
727 used
= terminal
->log_size
;
729 r_addr
= lxc_ringbuf_get_read_addr(buf
);
730 ret
= lxc_write_nointr(terminal
->log_fd
, r_addr
, used
);
737 void lxc_terminal_delete(struct lxc_terminal
*terminal
)
741 ret
= lxc_terminal_write_ringbuffer(terminal
);
743 WARN("Failed to write terminal log to disk");
745 if (terminal
->tios
&& terminal
->peer
>= 0) {
746 ret
= tcsetattr(terminal
->peer
, TCSAFLUSH
, terminal
->tios
);
748 WARN("%s - Failed to set old terminal settings", strerror(errno
));
750 free(terminal
->tios
);
751 terminal
->tios
= NULL
;
753 if (terminal
->peer
>= 0)
754 close(terminal
->peer
);
757 if (terminal
->master
>= 0)
758 close(terminal
->master
);
759 terminal
->master
= -1;
761 if (terminal
->slave
>= 0)
762 close(terminal
->slave
);
763 terminal
->slave
= -1;
765 if (terminal
->log_fd
>= 0)
766 close(terminal
->log_fd
);
767 terminal
->log_fd
= -1;
771 * Note that this function needs to run before the mainloop starts. Since we
772 * register a handler for the terminal's masterfd when we create the mainloop
773 * the terminal handler needs to see an allocated ringbuffer.
775 static int lxc_terminal_create_ringbuf(struct lxc_terminal
*terminal
)
778 struct lxc_ringbuf
*buf
= &terminal
->ringbuf
;
779 uint64_t size
= terminal
->buffer_size
;
781 /* no ringbuffer previously allocated and no ringbuffer requested */
782 if (!buf
->addr
&& size
<= 0)
785 /* ringbuffer allocated but no new ringbuffer requested */
786 if (buf
->addr
&& size
<= 0) {
787 lxc_ringbuf_release(buf
);
792 TRACE("Deallocated terminal ringbuffer");
799 /* check wether the requested size for the ringbuffer has changed */
800 if (buf
->addr
&& buf
->size
!= size
) {
801 TRACE("Terminal ringbuffer size changed from %" PRIu64
802 " to %" PRIu64
" bytes. Deallocating terminal ringbuffer",
804 lxc_ringbuf_release(buf
);
807 ret
= lxc_ringbuf_create(buf
, size
);
809 ERROR("Failed to setup %" PRIu64
" byte terminal ringbuffer", size
);
813 TRACE("Allocated %" PRIu64
" byte terminal ringbuffer", size
);
818 * This is the terminal log file. Please note that the terminal log file is
819 * (implementation wise not content wise) independent of the terminal ringbuffer.
821 int lxc_terminal_create_log_file(struct lxc_terminal
*terminal
)
823 if (!terminal
->log_path
)
826 terminal
->log_fd
= lxc_unpriv(open(terminal
->log_path
, O_CLOEXEC
| O_RDWR
| O_CREAT
| O_APPEND
, 0600));
827 if (terminal
->log_fd
< 0) {
828 SYSERROR("Failed to open terminal log file \"%s\"", terminal
->log_path
);
832 DEBUG("Using \"%s\" as terminal log file", terminal
->log_path
);
836 int lxc_terminal_create(struct lxc_terminal
*terminal
)
838 int ret
, saved_errno
;
840 ret
= openpty(&terminal
->master
, &terminal
->slave
, terminal
->name
, NULL
,
844 ERROR("%s - Failed to allocate a pty", strerror(saved_errno
));
848 ret
= fcntl(terminal
->master
, F_SETFD
, FD_CLOEXEC
);
850 SYSERROR("Failed to set FD_CLOEXEC flag on terminal master");
854 ret
= fcntl(terminal
->slave
, F_SETFD
, FD_CLOEXEC
);
856 SYSERROR("Failed to set FD_CLOEXEC flag on terminal slave");
860 ret
= lxc_terminal_peer_default(terminal
);
862 ERROR("Failed to allocate a peer pty device");
869 lxc_terminal_delete(terminal
);
873 int lxc_terminal_setup(struct lxc_conf
*conf
)
876 struct lxc_terminal
*terminal
= &conf
->console
;
878 if (terminal
->path
&& !strcmp(terminal
->path
, "none")) {
879 INFO("No terminal was requested");
883 ret
= lxc_terminal_create(terminal
);
887 /* create terminal log file */
888 ret
= lxc_terminal_create_log_file(terminal
);
892 /* create terminal ringbuffer */
893 ret
= lxc_terminal_create_ringbuf(terminal
);
900 lxc_terminal_delete(terminal
);
904 int lxc_terminal_set_stdfds(int fd
)
909 if (isatty(STDIN_FILENO
))
910 if (dup2(fd
, STDIN_FILENO
) < 0) {
911 SYSERROR("failed to duplicate stdin.");
915 if (isatty(STDOUT_FILENO
))
916 if (dup2(fd
, STDOUT_FILENO
) < 0) {
917 SYSERROR("failed to duplicate stdout.");
921 if (isatty(STDERR_FILENO
))
922 if (dup2(fd
, STDERR_FILENO
) < 0) {
923 SYSERROR("failed to duplicate stderr.");
930 int lxc_terminal_stdin_cb(int fd
, uint32_t events
, void *cbdata
,
931 struct lxc_epoll_descr
*descr
)
933 struct lxc_terminal_state
*ts
= cbdata
;
936 if (fd
!= ts
->stdinfd
)
937 return LXC_MAINLOOP_CLOSE
;
939 if (lxc_read_nointr(ts
->stdinfd
, &c
, 1) <= 0)
940 return LXC_MAINLOOP_CLOSE
;
942 if (ts
->escape
>= 1) {
943 /* we want to exit the terminal with Ctrl+a q */
944 if (c
== ts
->escape
&& !ts
->saw_escape
) {
949 if (c
== 'q' && ts
->saw_escape
)
950 return LXC_MAINLOOP_CLOSE
;
955 if (lxc_write_nointr(ts
->masterfd
, &c
, 1) <= 0)
956 return LXC_MAINLOOP_CLOSE
;
961 int lxc_terminal_master_cb(int fd
, uint32_t events
, void *cbdata
,
962 struct lxc_epoll_descr
*descr
)
964 struct lxc_terminal_state
*ts
= cbdata
;
965 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
968 if (fd
!= ts
->masterfd
)
969 return LXC_MAINLOOP_CLOSE
;
971 r
= lxc_read_nointr(fd
, buf
, sizeof(buf
));
973 return LXC_MAINLOOP_CLOSE
;
975 w
= lxc_write_nointr(ts
->stdoutfd
, buf
, r
);
977 return LXC_MAINLOOP_CLOSE
;
979 SYSERROR("Failed to write");
986 int lxc_terminal_getfd(struct lxc_container
*c
, int *ttynum
, int *masterfd
)
988 return lxc_cmd_console(c
->name
, ttynum
, masterfd
, c
->config_path
);
991 int lxc_console(struct lxc_container
*c
, int ttynum
,
992 int stdinfd
, int stdoutfd
, int stderrfd
,
995 int ret
, ttyfd
, masterfd
;
996 struct lxc_epoll_descr descr
;
997 struct termios oldtios
;
998 struct lxc_terminal_state
*ts
;
1001 ttyfd
= lxc_cmd_console(c
->name
, &ttynum
, &masterfd
, c
->config_path
);
1007 TRACE("Process is already group leader");
1009 ts
= lxc_terminal_signal_init(stdinfd
, masterfd
);
1014 ts
->escape
= escape
;
1015 ts
->winch_proxy
= c
->name
;
1016 ts
->winch_proxy_lxcpath
= c
->config_path
;
1017 ts
->stdoutfd
= stdoutfd
;
1019 istty
= isatty(stdinfd
);
1021 lxc_terminal_winsz(stdinfd
, masterfd
);
1022 lxc_cmd_terminal_winch(ts
->winch_proxy
, ts
->winch_proxy_lxcpath
);
1024 INFO("File descriptor %d does not refer to a tty device", stdinfd
);
1027 ret
= lxc_mainloop_open(&descr
);
1029 ERROR("Failed to create mainloop");
1033 if (ts
->sigfd
!= -1) {
1034 ret
= lxc_mainloop_add_handler(&descr
, ts
->sigfd
,
1035 lxc_terminal_signalfd_cb
, ts
);
1037 ERROR("Failed to add signal handler to mainloop");
1038 goto close_mainloop
;
1042 ret
= lxc_mainloop_add_handler(&descr
, ts
->stdinfd
,
1043 lxc_terminal_stdin_cb
, ts
);
1045 ERROR("Failed to add stdin handler");
1046 goto close_mainloop
;
1049 ret
= lxc_mainloop_add_handler(&descr
, ts
->masterfd
,
1050 lxc_terminal_master_cb
, ts
);
1052 ERROR("Failed to add master handler");
1053 goto close_mainloop
;
1056 if (ts
->escape
>= 1) {
1059 "Connected to tty %1$d\n"
1060 "Type <Ctrl+%2$c q> to exit the console, "
1061 "<Ctrl+%2$c Ctrl+%2$c> to enter Ctrl+%2$c itself\n",
1062 ttynum
, 'a' + escape
- 1);
1066 ret
= lxc_setup_tios(stdinfd
, &oldtios
);
1068 goto close_mainloop
;
1071 ret
= lxc_mainloop(&descr
, -1);
1073 ERROR("The mainloop returned an error");
1081 istty
= tcsetattr(stdinfd
, TCSAFLUSH
, &oldtios
);
1083 WARN("%s - Failed to restore terminal properties",
1088 lxc_mainloop_close(&descr
);
1091 lxc_terminal_signal_fini(ts
);
1100 int lxc_make_controlling_pty(int fd
)
1106 ret
= ioctl(fd
, TIOCSCTTY
, (char *)NULL
);
1113 int lxc_login_pty(int fd
)
1117 ret
= lxc_make_controlling_pty(fd
);
1121 ret
= lxc_terminal_set_stdfds(fd
);
1125 if (fd
> STDERR_FILENO
)
1131 void lxc_terminal_info_init(struct lxc_terminal_info
*pty
)
1133 pty
->name
[0] = '\0';
1134 pty
->master
= -EBADF
;
1135 pty
->slave
= -EBADF
;
1139 void lxc_terminal_init(struct lxc_terminal
*pty
)
1141 memset(pty
, 0, sizeof(*pty
));
1142 pty
->slave
= -EBADF
;
1143 pty
->master
= -EBADF
;
1145 pty
->log_fd
= -EBADF
;
1146 lxc_terminal_info_init(&pty
->peerpty
);
1149 void lxc_terminal_conf_free(struct lxc_terminal
*terminal
)
1151 free(terminal
->log_path
);
1152 free(terminal
->path
);
1153 if (terminal
->buffer_size
> 0 && terminal
->ringbuf
.addr
)
1154 lxc_ringbuf_release(&terminal
->ringbuf
);
1157 int lxc_terminal_map_ids(struct lxc_conf
*c
, struct lxc_terminal
*pty
)
1161 if (lxc_list_empty(&c
->id_map
))
1164 ret
= strcmp(pty
->name
, "");
1168 ret
= chown_mapped_root(pty
->name
, c
);
1170 ERROR("Failed to chown \"%s\"", pty
->name
);
1174 TRACE("Chowned \"%s\"", pty
->name
);