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>
45 #include "start.h" /* for struct lxc_handler */
51 #include <../include/openpty.h>
54 #define LXC_TERMINAL_BUFFER_SIZE 1024
56 lxc_log_define(console
, lxc
);
58 static struct lxc_list lxc_ttys
;
60 typedef void (*sighandler_t
)(int);
62 __attribute__((constructor
)) void lxc_terminal_init(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_tty_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_tty_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_tty_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_tty_state
*lxc_terminal_signal_init(int srcfd
, int dstfd
)
139 struct lxc_tty_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_tty_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_console_truncate_log_file(struct lxc_pty
*console
)
209 /* be very certain things are kosher */
210 if (!console
->log_path
|| console
->log_fd
< 0)
213 return lxc_unpriv(ftruncate(console
->log_fd
, 0));
216 static int lxc_console_rotate_log_file(struct lxc_pty
*console
)
222 if (!console
->log_path
|| console
->log_rotate
== 0)
225 /* be very certain things are kosher */
226 if (console
->log_fd
< 0)
229 len
= strlen(console
->log_path
) + sizeof(".1");
232 ret
= snprintf(tmp
, len
, "%s.1", console
->log_path
);
233 if (ret
< 0 || (size_t)ret
>= len
)
236 close(console
->log_fd
);
237 console
->log_fd
= -1;
238 ret
= lxc_unpriv(rename(console
->log_path
, tmp
));
242 return lxc_console_create_log_file(console
);
245 static int lxc_console_write_log_file(struct lxc_pty
*console
, char *buf
,
249 int64_t space_left
= -1;
252 if (console
->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 (console
->log_size
<= 0)
260 return lxc_write_nointr(console
->log_fd
, buf
, bytes_read
);
262 /* Get current size of the log file. */
263 ret
= fstat(console
->log_fd
, &st
);
265 SYSERROR("Failed to stat the console 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 (console
->log_rotate
> 0 || console
->log_size
> 0)
279 /* I mean, sure log wherever you want to. */
280 return lxc_write_nointr(console
->log_fd
, buf
, bytes_read
);
283 space_left
= console
->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 && console
->log_rotate
<= 0) {
289 ret
= lxc_console_truncate_log_file(console
);
293 if (bytes_read
<= console
->log_size
)
294 return lxc_write_nointr(console
->log_fd
, buf
, bytes_read
);
296 /* Write as much as we can into the buffer and loose the rest. */
297 return lxc_write_nointr(console
->log_fd
, buf
, console
->log_size
);
300 /* There's enough space left. */
301 if (bytes_read
<= space_left
)
302 return lxc_write_nointr(console
->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(console
->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 (console
->log_rotate
> 0)
318 ret
= lxc_console_rotate_log_file(console
);
320 ret
= lxc_console_truncate_log_file(console
);
324 if (console
->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 console 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 console log file is smaller than the bytes to write");
336 ret
= lxc_write_nointr(console
->log_fd
, buf
, console
->log_size
);
343 /* Yay, we made it. */
344 ret
= lxc_write_nointr(console
->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_pty
*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_pty
*console
)
414 if (console
->peer
>= 0) {
415 ret
= lxc_mainloop_add_handler(console
->descr
, console
->peer
,
416 lxc_terminal_io_cb
, console
);
418 WARN("Failed to add console peer handler to mainloop");
423 if (!console
->tty_state
|| console
->tty_state
->sigfd
< 0)
426 ret
= lxc_mainloop_add_handler(console
->descr
, console
->tty_state
->sigfd
,
427 lxc_terminal_signalfd_cb
, console
->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_pty
*console
)
441 if (console
->master
< 0) {
446 ret
= lxc_mainloop_add_handler(descr
, console
->master
,
447 lxc_terminal_io_cb
, console
);
449 ERROR("Failed to add handler for %d to mainloop", console
->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 console
->descr
= descr
;
457 ret
= lxc_terminal_mainloop_add_peer(console
);
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_pty
*console
)
514 if (console
->tty_state
) {
515 lxc_terminal_signal_fini(console
->tty_state
);
516 console
->tty_state
= NULL
;
518 close(console
->peerpty
.master
);
519 close(console
->peerpty
.slave
);
520 console
->peerpty
.master
= -1;
521 console
->peerpty
.slave
= -1;
522 console
->peerpty
.busy
= -1;
523 console
->peerpty
.name
[0] = '\0';
527 static int lxc_terminal_peer_proxy_alloc(struct lxc_pty
*console
, int sockfd
)
529 struct termios oldtermio
;
530 struct lxc_tty_state
*ts
;
533 if (console
->master
< 0) {
534 ERROR("console not set up");
537 if (console
->peerpty
.busy
!= -1 || console
->peer
!= -1) {
538 NOTICE("console already in use");
541 if (console
->tty_state
) {
542 ERROR("console 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(&console
->peerpty
.master
, &console
->peerpty
.slave
,
550 console
->peerpty
.name
, NULL
, NULL
);
552 SYSERROR("failed to create proxy pty");
556 if (lxc_setup_tios(console
->peerpty
.slave
, &oldtermio
) < 0)
559 ts
= lxc_terminal_signal_init(console
->peerpty
.master
, console
->master
);
563 console
->tty_state
= ts
;
564 console
->peer
= console
->peerpty
.slave
;
565 console
->peerpty
.busy
= sockfd
;
566 ret
= lxc_terminal_mainloop_add_peer(console
);
570 DEBUG("%d %s peermaster:%d sockfd:%d", lxc_raw_getpid(), __FUNCTION__
, console
->peerpty
.master
, sockfd
);
574 lxc_terminal_peer_proxy_free(console
);
578 int lxc_terminal_allocate(struct lxc_conf
*conf
, int sockfd
, int *ttyreq
)
580 int masterfd
= -1, ttynum
;
581 struct lxc_tty_info
*tty_info
= &conf
->tty_info
;
582 struct lxc_pty
*console
= &conf
->console
;
585 if (lxc_terminal_peer_proxy_alloc(console
, sockfd
) < 0)
587 masterfd
= console
->peerpty
.master
;
592 if (*ttyreq
> tty_info
->nbtty
)
595 if (tty_info
->pty_info
[*ttyreq
- 1].busy
)
598 /* the requested tty is available */
603 /* search for next available tty, fixup index tty1 => [0] */
604 for (ttynum
= 1; ttynum
<= tty_info
->nbtty
&& tty_info
->pty_info
[ttynum
- 1].busy
; ttynum
++)
607 /* we didn't find any available slot for tty */
608 if (ttynum
> tty_info
->nbtty
)
614 tty_info
->pty_info
[ttynum
- 1].busy
= sockfd
;
615 masterfd
= tty_info
->pty_info
[ttynum
- 1].master
;
620 void lxc_terminal_free(struct lxc_conf
*conf
, int fd
)
623 struct lxc_tty_info
*tty_info
= &conf
->tty_info
;
624 struct lxc_pty
*console
= &conf
->console
;
626 for (i
= 0; i
< tty_info
->nbtty
; i
++) {
627 if (tty_info
->pty_info
[i
].busy
== fd
)
628 tty_info
->pty_info
[i
].busy
= 0;
631 if (console
->peerpty
.busy
== fd
) {
632 lxc_mainloop_del_handler(console
->descr
, console
->peerpty
.slave
);
633 lxc_terminal_peer_proxy_free(console
);
637 static int lxc_terminal_peer_default(struct lxc_pty
*console
)
639 struct lxc_tty_state
*ts
;
640 const char *path
= console
->path
;
644 /* If no console 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 console
->peer
= lxc_unpriv(open(path
, O_RDWR
| O_CLOEXEC
));
662 if (console
->peer
< 0) {
663 ERROR("Failed to open \"%s\": %s", path
, strerror(errno
));
666 DEBUG("using \"%s\" as peer tty device", path
);
668 if (!isatty(console
->peer
)) {
669 ERROR("file descriptor for file \"%s\" does not refer to a tty device", path
);
673 ts
= lxc_terminal_signal_init(console
->peer
, console
->master
);
674 console
->tty_state
= ts
;
676 WARN("Failed to install signal handler");
680 lxc_terminal_winsz(console
->peer
, console
->master
);
682 console
->tios
= malloc(sizeof(*console
->tios
));
683 if (!console
->tios
) {
684 SYSERROR("failed to allocate memory");
688 if (lxc_setup_tios(console
->peer
, console
->tios
) < 0)
695 console
->tios
= NULL
;
698 close(console
->peer
);
706 int lxc_terminal_write_ringbuffer(struct lxc_pty
*console
)
711 struct lxc_ringbuf
*buf
= &console
->ringbuf
;
713 /* There's not log file where we can dump the ringbuffer to. */
714 if (console
->log_fd
< 0)
717 /* The log file is simply appended to. */
718 if (console
->log_size
== 0)
721 used
= lxc_ringbuf_used(buf
);
725 ret
= lxc_console_truncate_log_file(console
);
729 /* Write as much as we can without exceeding the limit. */
730 if (console
->log_size
< used
)
731 used
= console
->log_size
;
733 r_addr
= lxc_ringbuf_get_read_addr(buf
);
734 ret
= lxc_write_nointr(console
->log_fd
, r_addr
, used
);
741 void lxc_terminal_delete(struct lxc_pty
*console
)
745 ret
= lxc_terminal_write_ringbuffer(console
);
747 WARN("Failed to write console ringbuffer to console log file");
749 if (console
->tios
&& console
->peer
>= 0) {
750 ret
= tcsetattr(console
->peer
, TCSAFLUSH
, console
->tios
);
752 WARN("%s - Failed to set old terminal settings", strerror(errno
));
755 console
->tios
= NULL
;
757 if (console
->peer
>= 0)
758 close(console
->peer
);
761 if (console
->master
>= 0)
762 close(console
->master
);
763 console
->master
= -1;
765 if (console
->slave
>= 0)
766 close(console
->slave
);
769 if (console
->log_fd
>= 0)
770 close(console
->log_fd
);
771 console
->log_fd
= -1;
775 * Note that this function needs to run before the mainloop starts. Since we
776 * register a handler for the console's masterfd when we create the mainloop
777 * the console handler needs to see an allocated ringbuffer.
779 static int lxc_terminal_create_ringbuf(struct lxc_pty
*console
)
782 struct lxc_ringbuf
*buf
= &console
->ringbuf
;
783 uint64_t size
= console
->buffer_size
;
785 /* no ringbuffer previously allocated and no ringbuffer requested */
786 if (!buf
->addr
&& size
<= 0)
789 /* ringbuffer allocated but no new ringbuffer requested */
790 if (buf
->addr
&& size
<= 0) {
791 lxc_ringbuf_release(buf
);
796 TRACE("Deallocated console ringbuffer");
803 /* check wether the requested size for the ringbuffer has changed */
804 if (buf
->addr
&& buf
->size
!= size
) {
805 TRACE("Console ringbuffer size changed from %" PRIu64
806 " to %" PRIu64
" bytes. Deallocating console ringbuffer",
808 lxc_ringbuf_release(buf
);
811 ret
= lxc_ringbuf_create(buf
, size
);
813 ERROR("Failed to setup %" PRIu64
" byte console ringbuffer", size
);
817 TRACE("Allocated %" PRIu64
" byte console ringbuffer", size
);
822 * This is the console log file. Please note that the console log file is
823 * (implementation wise not content wise) independent of the console ringbuffer.
825 int lxc_terminal_create_log_file(struct lxc_pty
*console
)
827 if (!console
->log_path
)
830 console
->log_fd
= lxc_unpriv(open(console
->log_path
, O_CLOEXEC
| O_RDWR
| O_CREAT
| O_APPEND
, 0600));
831 if (console
->log_fd
< 0) {
832 SYSERROR("Failed to open console log file \"%s\"", console
->log_path
);
836 DEBUG("Using \"%s\" as console log file", console
->log_path
);
840 int lxc_pty_create(struct lxc_pty
*console
)
842 int ret
, saved_errno
;
844 ret
= openpty(&console
->master
, &console
->slave
, console
->name
, NULL
,
848 ERROR("%s - Failed to allocate a pty", strerror(saved_errno
));
852 ret
= fcntl(console
->master
, F_SETFD
, FD_CLOEXEC
);
854 SYSERROR("Failed to set FD_CLOEXEC flag on console master");
858 ret
= fcntl(console
->slave
, F_SETFD
, FD_CLOEXEC
);
860 SYSERROR("Failed to set FD_CLOEXEC flag on console slave");
864 ret
= lxc_terminal_peer_default(console
);
866 ERROR("Failed to allocate a peer pty device");
873 lxc_terminal_delete(console
);
877 int lxc_terminal_create(struct lxc_conf
*conf
)
880 struct lxc_pty
*console
= &conf
->console
;
882 if (console
->path
&& !strcmp(console
->path
, "none")) {
883 INFO("No console was requested");
887 ret
= lxc_pty_create(console
);
891 /* create console log file */
892 ret
= lxc_terminal_create_log_file(console
);
896 /* create console ringbuffer */
897 ret
= lxc_terminal_create_ringbuf(console
);
904 lxc_terminal_delete(console
);
908 int lxc_terminal_set_stdfds(int fd
)
913 if (isatty(STDIN_FILENO
))
914 if (dup2(fd
, STDIN_FILENO
) < 0) {
915 SYSERROR("failed to duplicate stdin.");
919 if (isatty(STDOUT_FILENO
))
920 if (dup2(fd
, STDOUT_FILENO
) < 0) {
921 SYSERROR("failed to duplicate stdout.");
925 if (isatty(STDERR_FILENO
))
926 if (dup2(fd
, STDERR_FILENO
) < 0) {
927 SYSERROR("failed to duplicate stderr.");
934 int lxc_console_cb_tty_stdin(int fd
, uint32_t events
, void *cbdata
,
935 struct lxc_epoll_descr
*descr
)
937 struct lxc_tty_state
*ts
= cbdata
;
940 if (fd
!= ts
->stdinfd
)
941 return LXC_MAINLOOP_CLOSE
;
943 if (lxc_read_nointr(ts
->stdinfd
, &c
, 1) <= 0)
944 return LXC_MAINLOOP_CLOSE
;
946 if (ts
->escape
>= 1) {
947 /* we want to exit the console with Ctrl+a q */
948 if (c
== ts
->escape
&& !ts
->saw_escape
) {
953 if (c
== 'q' && ts
->saw_escape
)
954 return LXC_MAINLOOP_CLOSE
;
959 if (lxc_write_nointr(ts
->masterfd
, &c
, 1) <= 0)
960 return LXC_MAINLOOP_CLOSE
;
965 int lxc_console_cb_tty_master(int fd
, uint32_t events
, void *cbdata
,
966 struct lxc_epoll_descr
*descr
)
968 struct lxc_tty_state
*ts
= cbdata
;
969 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
972 if (fd
!= ts
->masterfd
)
973 return LXC_MAINLOOP_CLOSE
;
975 r
= lxc_read_nointr(fd
, buf
, sizeof(buf
));
977 return LXC_MAINLOOP_CLOSE
;
979 w
= lxc_write_nointr(ts
->stdoutfd
, buf
, r
);
981 return LXC_MAINLOOP_CLOSE
;
983 SYSERROR("Failed to write");
990 int lxc_console_getfd(struct lxc_container
*c
, int *ttynum
, int *masterfd
)
992 return lxc_cmd_console(c
->name
, ttynum
, masterfd
, c
->config_path
);
995 int lxc_console(struct lxc_container
*c
, int ttynum
,
996 int stdinfd
, int stdoutfd
, int stderrfd
,
999 int ret
, ttyfd
, masterfd
;
1000 struct lxc_epoll_descr descr
;
1001 struct termios oldtios
;
1002 struct lxc_tty_state
*ts
;
1005 ttyfd
= lxc_cmd_console(c
->name
, &ttynum
, &masterfd
, c
->config_path
);
1011 TRACE("Process is already group leader");
1013 ts
= lxc_terminal_signal_init(stdinfd
, masterfd
);
1018 ts
->escape
= escape
;
1019 ts
->winch_proxy
= c
->name
;
1020 ts
->winch_proxy_lxcpath
= c
->config_path
;
1021 ts
->stdoutfd
= stdoutfd
;
1023 istty
= isatty(stdinfd
);
1025 lxc_terminal_winsz(stdinfd
, masterfd
);
1026 lxc_cmd_terminal_winch(ts
->winch_proxy
, ts
->winch_proxy_lxcpath
);
1028 INFO("File descriptor %d does not refer to a tty device", stdinfd
);
1031 ret
= lxc_mainloop_open(&descr
);
1033 ERROR("Failed to create mainloop");
1037 if (ts
->sigfd
!= -1) {
1038 ret
= lxc_mainloop_add_handler(&descr
, ts
->sigfd
,
1039 lxc_terminal_signalfd_cb
, ts
);
1041 ERROR("Failed to add signal handler to mainloop");
1042 goto close_mainloop
;
1046 ret
= lxc_mainloop_add_handler(&descr
, ts
->stdinfd
,
1047 lxc_console_cb_tty_stdin
, ts
);
1049 ERROR("Failed to add stdin handler");
1050 goto close_mainloop
;
1053 ret
= lxc_mainloop_add_handler(&descr
, ts
->masterfd
,
1054 lxc_console_cb_tty_master
, ts
);
1056 ERROR("Failed to add master handler");
1057 goto close_mainloop
;
1060 if (ts
->escape
>= 1) {
1063 "Connected to tty %1$d\n"
1064 "Type <Ctrl+%2$c q> to exit the console, "
1065 "<Ctrl+%2$c Ctrl+%2$c> to enter Ctrl+%2$c itself\n",
1066 ttynum
, 'a' + escape
- 1);
1070 ret
= lxc_setup_tios(stdinfd
, &oldtios
);
1072 goto close_mainloop
;
1075 ret
= lxc_mainloop(&descr
, -1);
1077 ERROR("The mainloop returned an error");
1085 istty
= tcsetattr(stdinfd
, TCSAFLUSH
, &oldtios
);
1087 WARN("%s - Failed to restore terminal properties",
1092 lxc_mainloop_close(&descr
);
1095 lxc_terminal_signal_fini(ts
);
1104 int lxc_make_controlling_pty(int fd
)
1110 ret
= ioctl(fd
, TIOCSCTTY
, (char *)NULL
);
1117 int lxc_login_pty(int fd
)
1121 ret
= lxc_make_controlling_pty(fd
);
1125 ret
= lxc_terminal_set_stdfds(fd
);
1129 if (fd
> STDERR_FILENO
)
1135 void lxc_pty_info_init(struct lxc_pty_info
*pty
)
1137 pty
->name
[0] = '\0';
1138 pty
->master
= -EBADF
;
1139 pty
->slave
= -EBADF
;
1143 void lxc_pty_init(struct lxc_pty
*pty
)
1145 memset(pty
, 0, sizeof(*pty
));
1146 pty
->slave
= -EBADF
;
1147 pty
->master
= -EBADF
;
1149 pty
->log_fd
= -EBADF
;
1150 lxc_pty_info_init(&pty
->peerpty
);
1153 void lxc_pty_conf_free(struct lxc_pty
*console
)
1155 free(console
->log_path
);
1156 free(console
->path
);
1157 if (console
->buffer_size
> 0 && console
->ringbuf
.addr
)
1158 lxc_ringbuf_release(&console
->ringbuf
);
1161 int lxc_pty_map_ids(struct lxc_conf
*c
, struct lxc_pty
*pty
)
1165 if (lxc_list_empty(&c
->id_map
))
1168 ret
= strcmp(pty
->name
, "");
1172 ret
= chown_mapped_root(pty
->name
, c
);
1174 ERROR("Failed to chown \"%s\"", pty
->name
);
1178 TRACE("Chowned \"%s\"", pty
->name
);