]>
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
26 #include <lxc/lxccontainer.h>
30 #include <sys/epoll.h>
31 #include <sys/types.h>
50 #include <../include/openpty.h>
53 #define LXC_TERMINAL_BUFFER_SIZE 1024
55 lxc_log_define(terminal
, lxc
);
57 static struct lxc_list lxc_ttys
;
59 typedef void (*sighandler_t
)(int);
61 __attribute__((constructor
)) void lxc_terminal_init_global(void)
63 lxc_list_init(&lxc_ttys
);
66 void lxc_terminal_winsz(int srcfd
, int dstfd
)
74 ret
= ioctl(srcfd
, TIOCGWINSZ
, &wsz
);
76 WARN("Failed to get window size");
80 ret
= ioctl(dstfd
, TIOCSWINSZ
, &wsz
);
82 WARN("Failed to set window size");
84 DEBUG("Set window size to %d columns and %d rows", wsz
.ws_col
,
90 static void lxc_terminal_winch(struct lxc_terminal_state
*ts
)
92 lxc_terminal_winsz(ts
->stdinfd
, ts
->masterfd
);
95 lxc_cmd_terminal_winch(ts
->winch_proxy
, ts
->winch_proxy_lxcpath
);
98 void lxc_terminal_sigwinch(int sig
)
101 struct lxc_terminal_state
*ts
;
103 lxc_list_for_each(it
, &lxc_ttys
) {
105 lxc_terminal_winch(ts
);
109 int lxc_terminal_signalfd_cb(int fd
, uint32_t events
, void *cbdata
,
110 struct lxc_epoll_descr
*descr
)
113 struct signalfd_siginfo siginfo
;
114 struct lxc_terminal_state
*ts
= cbdata
;
116 ret
= read(fd
, &siginfo
, sizeof(siginfo
));
117 if (ret
< 0 || (size_t)ret
< sizeof(siginfo
)) {
118 ERROR("Failed to read signal info");
119 return LXC_MAINLOOP_ERROR
;
122 if (siginfo
.ssi_signo
== SIGTERM
) {
123 DEBUG("Received SIGTERM. Detaching from the terminal");
124 return LXC_MAINLOOP_CLOSE
;
127 if (siginfo
.ssi_signo
== SIGWINCH
)
128 lxc_terminal_winch(ts
);
130 return LXC_MAINLOOP_CONTINUE
;
133 struct lxc_terminal_state
*lxc_terminal_signal_init(int srcfd
, int dstfd
)
138 struct lxc_terminal_state
*ts
;
140 ts
= malloc(sizeof(*ts
));
144 memset(ts
, 0, sizeof(*ts
));
146 ts
->masterfd
= dstfd
;
149 ret
= sigemptyset(&mask
);
151 SYSERROR("Failed to initialize an empty signal set");
155 istty
= (isatty(srcfd
) == 1);
157 INFO("fd %d does not refer to a tty device", srcfd
);
159 /* Add tty to list to be scanned at SIGWINCH time. */
160 lxc_list_add_elem(&ts
->node
, ts
);
161 lxc_list_add_tail(&lxc_ttys
, &ts
->node
);
162 ret
= sigaddset(&mask
, SIGWINCH
);
164 NOTICE("%s - Failed to add SIGWINCH to signal set",
168 /* Exit the mainloop cleanly on SIGTERM. */
169 ret
= sigaddset(&mask
, SIGTERM
);
171 SYSERROR("Failed to add SIGWINCH to signal set");
175 ret
= sigprocmask(SIG_BLOCK
, &mask
, &ts
->oldmask
);
177 WARN("Failed to block signals");
181 ts
->sigfd
= signalfd(-1, &mask
, SFD_CLOEXEC
);
183 WARN("Failed to create signal fd");
184 sigprocmask(SIG_SETMASK
, &ts
->oldmask
, NULL
);
188 DEBUG("Created signal fd %d", ts
->sigfd
);
192 ERROR("Failed to create signal fd");
193 if (ts
->sigfd
>= 0) {
199 lxc_list_del(&ts
->node
);
204 void lxc_terminal_signal_fini(struct lxc_terminal_state
*ts
)
206 if (ts
->sigfd
>= 0) {
209 if (sigprocmask(SIG_SETMASK
, &ts
->oldmask
, NULL
) < 0)
210 WARN("%s - Failed to restore signal mask", strerror(errno
));
213 if (isatty(ts
->stdinfd
))
214 lxc_list_del(&ts
->node
);
219 static int lxc_terminal_truncate_log_file(struct lxc_terminal
*terminal
)
221 /* be very certain things are kosher */
222 if (!terminal
->log_path
|| terminal
->log_fd
< 0)
225 return lxc_unpriv(ftruncate(terminal
->log_fd
, 0));
228 static int lxc_terminal_rotate_log_file(struct lxc_terminal
*terminal
)
234 if (!terminal
->log_path
|| terminal
->log_rotate
== 0)
237 /* be very certain things are kosher */
238 if (terminal
->log_fd
< 0)
241 len
= strlen(terminal
->log_path
) + sizeof(".1");
244 ret
= snprintf(tmp
, len
, "%s.1", terminal
->log_path
);
245 if (ret
< 0 || (size_t)ret
>= len
)
248 close(terminal
->log_fd
);
249 terminal
->log_fd
= -1;
250 ret
= lxc_unpriv(rename(terminal
->log_path
, tmp
));
254 return lxc_terminal_create_log_file(terminal
);
257 static int lxc_terminal_write_log_file(struct lxc_terminal
*terminal
, char *buf
,
262 int64_t space_left
= -1;
264 if (terminal
->log_fd
< 0)
267 /* A log size <= 0 means that there's no limit on the size of the log
268 * file at which point we simply ignore whether the log is supposed to
271 if (terminal
->log_size
<= 0)
272 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
274 /* Get current size of the log file. */
275 ret
= fstat(terminal
->log_fd
, &st
);
277 SYSERROR("Failed to stat the terminal log file descriptor");
281 /* handle non-regular files */
282 if ((st
.st_mode
& S_IFMT
) != S_IFREG
) {
283 /* This isn't a regular file. so rotating the file seems a
284 * dangerous thing to do, size limits are also very
285 * questionable. Let's not risk anything and tell the user that
286 * he's requesting us to do weird stuff.
288 if (terminal
->log_rotate
> 0 || terminal
->log_size
> 0)
291 /* I mean, sure log wherever you want to. */
292 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
295 space_left
= terminal
->log_size
- st
.st_size
;
297 /* User doesn't want to rotate the log file and there's no more space
298 * left so simply truncate it.
300 if (space_left
<= 0 && terminal
->log_rotate
<= 0) {
301 ret
= lxc_terminal_truncate_log_file(terminal
);
305 if (bytes_read
<= terminal
->log_size
)
306 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
308 /* Write as much as we can into the buffer and loose the rest. */
309 return lxc_write_nointr(terminal
->log_fd
, buf
, terminal
->log_size
);
312 /* There's enough space left. */
313 if (bytes_read
<= space_left
)
314 return lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
316 /* There's not enough space left but at least write as much as we can
317 * into the old log file.
319 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, space_left
);
323 /* Calculate how many bytes we still need to write. */
324 bytes_read
-= space_left
;
326 /* There'd be more to write but we aren't instructed to rotate the log
327 * file so simply return. There's no error on our side here.
329 if (terminal
->log_rotate
> 0)
330 ret
= lxc_terminal_rotate_log_file(terminal
);
332 ret
= lxc_terminal_truncate_log_file(terminal
);
336 if (terminal
->log_size
< bytes_read
) {
337 /* Well, this is unfortunate because it means that there is more
338 * to write than the user has granted us space. There are
339 * multiple ways to handle this but let's use the simplest one:
340 * write as much as we can, tell the user that there was more
341 * stuff to write and move on.
342 * Note that this scenario shouldn't actually happen with the
343 * standard pty-based terminal that LXC allocates since it will
344 * be switched into raw mode. In raw mode only 1 byte at a time
345 * should be read and written.
347 WARN("Size of terminal log file is smaller than the bytes to write");
348 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, terminal
->log_size
);
355 /* Yay, we made it. */
356 ret
= lxc_write_nointr(terminal
->log_fd
, buf
, bytes_read
);
363 int lxc_terminal_io_cb(int fd
, uint32_t events
, void *data
,
364 struct lxc_epoll_descr
*descr
)
366 struct lxc_terminal
*terminal
= data
;
367 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
368 int r
, w
, w_log
, w_rbuf
;
370 w
= r
= lxc_read_nointr(fd
, buf
, sizeof(buf
));
372 INFO("Terminal client on fd %d has exited", fd
);
373 lxc_mainloop_del_handler(descr
, fd
);
375 if (fd
== terminal
->master
) {
376 terminal
->master
= -EBADF
;
377 } else if (fd
== terminal
->peer
) {
378 if (terminal
->tty_state
) {
379 lxc_terminal_signal_fini(terminal
->tty_state
);
380 terminal
->tty_state
= NULL
;
382 terminal
->peer
= -EBADF
;
384 ERROR("Handler received unexpected file descriptor");
388 return LXC_MAINLOOP_CLOSE
;
391 if (fd
== terminal
->peer
)
392 w
= lxc_write_nointr(terminal
->master
, buf
, r
);
395 if (fd
== terminal
->master
) {
396 /* write to peer first */
397 if (terminal
->peer
>= 0)
398 w
= lxc_write_nointr(terminal
->peer
, buf
, r
);
400 /* write to terminal ringbuffer */
401 if (terminal
->buffer_size
> 0)
402 w_rbuf
= lxc_ringbuf_write(&terminal
->ringbuf
, buf
, r
);
404 /* write to terminal log */
405 if (terminal
->log_fd
>= 0)
406 w_log
= lxc_terminal_write_log_file(terminal
, buf
, r
);
410 WARN("Short write on terminal r:%d != w:%d", r
, w
);
413 TRACE("%s - Failed to write %d bytes to terminal ringbuffer",
414 strerror(-w_rbuf
), r
);
417 TRACE("Failed to write %d bytes to terminal log", r
);
419 return LXC_MAINLOOP_CONTINUE
;
422 static int lxc_terminal_mainloop_add_peer(struct lxc_terminal
*terminal
)
426 if (terminal
->peer
>= 0) {
427 ret
= lxc_mainloop_add_handler(terminal
->descr
, terminal
->peer
,
428 lxc_terminal_io_cb
, terminal
);
430 WARN("Failed to add terminal peer handler to mainloop");
435 if (!terminal
->tty_state
|| terminal
->tty_state
->sigfd
< 0)
438 ret
= lxc_mainloop_add_handler(terminal
->descr
, terminal
->tty_state
->sigfd
,
439 lxc_terminal_signalfd_cb
, terminal
->tty_state
);
441 WARN("Failed to add signal handler to mainloop");
448 int lxc_terminal_mainloop_add(struct lxc_epoll_descr
*descr
,
449 struct lxc_terminal
*terminal
)
453 if (terminal
->master
< 0) {
454 INFO("Terminal is not initialized");
458 ret
= lxc_mainloop_add_handler(descr
, terminal
->master
,
459 lxc_terminal_io_cb
, terminal
);
461 ERROR("Failed to add handler for terminal master fd %d to "
462 "mainloop", terminal
->master
);
466 /* We cache the descr so that we can add an fd to it when someone
467 * does attach to it in lxc_terminal_allocate().
469 terminal
->descr
= descr
;
471 return lxc_terminal_mainloop_add_peer(terminal
);
474 int lxc_setup_tios(int fd
, struct termios
*oldtios
)
477 struct termios newtios
;
480 ERROR("File descriptor %d does not refert to a terminal", fd
);
484 /* Get current termios. */
485 ret
= tcgetattr(fd
, oldtios
);
487 SYSERROR("Failed to get current terminal settings");
491 /* ensure we don't end up in an endless loop:
492 * The kernel might fire SIGTTOU while an
493 * ioctl() in tcsetattr() is executed. When the ioctl()
494 * is resumed and retries, the signal handler interrupts it again.
496 signal (SIGTTIN
, SIG_IGN
);
497 signal (SIGTTOU
, SIG_IGN
);
501 /* We use the same settings that ssh does. */
502 newtios
.c_iflag
|= IGNPAR
;
503 newtios
.c_iflag
&= ~(ISTRIP
| INLCR
| IGNCR
| ICRNL
| IXON
| IXANY
| IXOFF
);
505 newtios
.c_iflag
&= ~IUCLC
;
507 newtios
.c_lflag
&= ~(TOSTOP
| ISIG
| ICANON
| ECHO
| ECHOE
| ECHOK
| ECHONL
);
509 newtios
.c_lflag
&= ~IEXTEN
;
511 newtios
.c_oflag
&= ~OPOST
;
512 newtios
.c_cc
[VMIN
] = 1;
513 newtios
.c_cc
[VTIME
] = 0;
515 /* Set new attributes. */
516 ret
= tcsetattr(fd
, TCSAFLUSH
, &newtios
);
518 ERROR("Failed to set new terminal settings");
525 static void lxc_terminal_peer_proxy_free(struct lxc_terminal
*terminal
)
527 if (terminal
->tty_state
) {
528 lxc_terminal_signal_fini(terminal
->tty_state
);
529 terminal
->tty_state
= NULL
;
532 close(terminal
->proxy
.master
);
533 terminal
->proxy
.master
= -1;
535 close(terminal
->proxy
.slave
);
536 terminal
->proxy
.slave
= -1;
538 terminal
->proxy
.busy
= -1;
540 terminal
->proxy
.name
[0] = '\0';
545 static int lxc_terminal_peer_proxy_alloc(struct lxc_terminal
*terminal
,
549 struct termios oldtermio
;
550 struct lxc_terminal_state
*ts
;
552 if (terminal
->master
< 0) {
553 ERROR("Terminal not set up");
557 if (terminal
->proxy
.busy
!= -1 || terminal
->peer
!= -1) {
558 NOTICE("Terminal already in use");
562 if (terminal
->tty_state
) {
563 ERROR("Terminal has already been initialized");
567 /* This is the proxy pty that will be given to the client, and that
568 * the real pty master will send to / recv from.
570 ret
= openpty(&terminal
->proxy
.master
, &terminal
->proxy
.slave
,
571 terminal
->proxy
.name
, NULL
, NULL
);
573 SYSERROR("Failed to open proxy terminal");
577 ret
= lxc_setup_tios(terminal
->proxy
.slave
, &oldtermio
);
581 ts
= lxc_terminal_signal_init(terminal
->proxy
.master
, terminal
->master
);
585 terminal
->tty_state
= ts
;
586 terminal
->peer
= terminal
->proxy
.slave
;
587 terminal
->proxy
.busy
= sockfd
;
588 ret
= lxc_terminal_mainloop_add_peer(terminal
);
592 NOTICE("Opened proxy terminal with master fd %d and slave fd %d",
593 terminal
->proxy
.master
, terminal
->proxy
.slave
);
597 lxc_terminal_peer_proxy_free(terminal
);
601 int lxc_terminal_allocate(struct lxc_conf
*conf
, int sockfd
, int *ttyreq
)
605 struct lxc_tty_info
*ttys
= &conf
->ttys
;
606 struct lxc_terminal
*terminal
= &conf
->console
;
611 ret
= lxc_terminal_peer_proxy_alloc(terminal
, sockfd
);
615 masterfd
= terminal
->proxy
.master
;
620 if (*ttyreq
> ttys
->nbtty
)
623 if (ttys
->tty
[*ttyreq
- 1].busy
)
626 /* The requested tty is available. */
631 /* Search for next available tty, fixup index tty1 => [0]. */
632 for (ttynum
= 1; ttynum
<= ttys
->nbtty
&& ttys
->tty
[ttynum
- 1].busy
; ttynum
++) {
636 /* We didn't find any available slot for tty. */
637 if (ttynum
> ttys
->nbtty
)
643 ttys
->tty
[ttynum
- 1].busy
= sockfd
;
644 masterfd
= ttys
->tty
[ttynum
- 1].master
;
650 void lxc_terminal_free(struct lxc_conf
*conf
, int fd
)
653 struct lxc_tty_info
*ttys
= &conf
->ttys
;
654 struct lxc_terminal
*terminal
= &conf
->console
;
656 for (i
= 0; i
< ttys
->nbtty
; i
++)
657 if (ttys
->tty
[i
].busy
== fd
)
658 ttys
->tty
[i
].busy
= 0;
660 if (terminal
->proxy
.busy
!= fd
)
663 lxc_mainloop_del_handler(terminal
->descr
, terminal
->proxy
.slave
);
664 lxc_terminal_peer_proxy_free(terminal
);
667 static int lxc_terminal_peer_default(struct lxc_terminal
*terminal
)
669 struct lxc_terminal_state
*ts
;
670 const char *path
= terminal
->path
;
675 ret
= access("/dev/tty", F_OK
);
677 /* If no terminal was given, try current controlling
678 * terminal, there won't be one if we were started as a
681 fd
= open("/dev/tty", O_RDWR
);
691 DEBUG("Theh process does not have a controlling terminal");
695 terminal
->peer
= lxc_unpriv(open(path
, O_RDWR
| O_CLOEXEC
));
696 if (terminal
->peer
< 0) {
697 ERROR("%s - Failed to open proxy terminal \"%s\"",
698 strerror(errno
), path
);
701 DEBUG("Using terminal \"%s\" as proxy", path
);
703 if (!isatty(terminal
->peer
)) {
704 ERROR("File descriptor for \"%s\" does not refer to a terminal", path
);
705 goto on_error_free_tios
;
708 ts
= lxc_terminal_signal_init(terminal
->peer
, terminal
->master
);
709 terminal
->tty_state
= ts
;
711 WARN("Failed to install signal handler");
712 goto on_error_free_tios
;
715 lxc_terminal_winsz(terminal
->peer
, terminal
->master
);
717 terminal
->tios
= malloc(sizeof(*terminal
->tios
));
719 goto on_error_free_tios
;
721 ret
= lxc_setup_tios(terminal
->peer
, terminal
->tios
);
723 goto on_error_close_peer
;
728 free(terminal
->tios
);
729 terminal
->tios
= NULL
;
732 close(terminal
->peer
);
740 int lxc_terminal_write_ringbuffer(struct lxc_terminal
*terminal
)
745 struct lxc_ringbuf
*buf
= &terminal
->ringbuf
;
747 /* There's not log file where we can dump the ringbuffer to. */
748 if (terminal
->log_fd
< 0)
751 used
= lxc_ringbuf_used(buf
);
755 ret
= lxc_terminal_truncate_log_file(terminal
);
759 /* Write as much as we can without exceeding the limit. */
760 if (terminal
->log_size
< used
)
761 used
= terminal
->log_size
;
763 r_addr
= lxc_ringbuf_get_read_addr(buf
);
764 ret
= lxc_write_nointr(terminal
->log_fd
, r_addr
, used
);
771 void lxc_terminal_delete(struct lxc_terminal
*terminal
)
775 ret
= lxc_terminal_write_ringbuffer(terminal
);
777 WARN("Failed to write terminal log to disk");
779 if (terminal
->tios
&& terminal
->peer
>= 0) {
780 ret
= tcsetattr(terminal
->peer
, TCSAFLUSH
, terminal
->tios
);
782 WARN("%s - Failed to set old terminal settings", strerror(errno
));
784 free(terminal
->tios
);
785 terminal
->tios
= NULL
;
787 if (terminal
->peer
>= 0)
788 close(terminal
->peer
);
791 if (terminal
->master
>= 0)
792 close(terminal
->master
);
793 terminal
->master
= -1;
795 if (terminal
->slave
>= 0)
796 close(terminal
->slave
);
797 terminal
->slave
= -1;
799 if (terminal
->log_fd
>= 0)
800 close(terminal
->log_fd
);
801 terminal
->log_fd
= -1;
805 * Note that this function needs to run before the mainloop starts. Since we
806 * register a handler for the terminal's masterfd when we create the mainloop
807 * the terminal handler needs to see an allocated ringbuffer.
809 static int lxc_terminal_create_ringbuf(struct lxc_terminal
*terminal
)
812 struct lxc_ringbuf
*buf
= &terminal
->ringbuf
;
813 uint64_t size
= terminal
->buffer_size
;
815 /* no ringbuffer previously allocated and no ringbuffer requested */
816 if (!buf
->addr
&& size
<= 0)
819 /* ringbuffer allocated but no new ringbuffer requested */
820 if (buf
->addr
&& size
<= 0) {
821 lxc_ringbuf_release(buf
);
826 TRACE("Deallocated terminal ringbuffer");
833 /* check wether the requested size for the ringbuffer has changed */
834 if (buf
->addr
&& buf
->size
!= size
) {
835 TRACE("Terminal ringbuffer size changed from %" PRIu64
836 " to %" PRIu64
" bytes. Deallocating terminal ringbuffer",
838 lxc_ringbuf_release(buf
);
841 ret
= lxc_ringbuf_create(buf
, size
);
843 ERROR("Failed to setup %" PRIu64
" byte terminal ringbuffer", size
);
847 TRACE("Allocated %" PRIu64
" byte terminal ringbuffer", size
);
852 * This is the terminal log file. Please note that the terminal log file is
853 * (implementation wise not content wise) independent of the terminal ringbuffer.
855 int lxc_terminal_create_log_file(struct lxc_terminal
*terminal
)
857 if (!terminal
->log_path
)
860 terminal
->log_fd
= lxc_unpriv(open(terminal
->log_path
, O_CLOEXEC
| O_RDWR
| O_CREAT
| O_APPEND
, 0600));
861 if (terminal
->log_fd
< 0) {
862 SYSERROR("Failed to open terminal log file \"%s\"", terminal
->log_path
);
866 DEBUG("Using \"%s\" as terminal log file", terminal
->log_path
);
870 int lxc_terminal_create(struct lxc_terminal
*terminal
)
874 ret
= openpty(&terminal
->master
, &terminal
->slave
, terminal
->name
, NULL
, NULL
);
876 SYSERROR("Failed to open terminal");
880 ret
= fcntl(terminal
->master
, F_SETFD
, FD_CLOEXEC
);
882 SYSERROR("Failed to set FD_CLOEXEC flag on terminal master");
886 ret
= fcntl(terminal
->slave
, F_SETFD
, FD_CLOEXEC
);
888 SYSERROR("Failed to set FD_CLOEXEC flag on terminal slave");
892 ret
= lxc_terminal_peer_default(terminal
);
894 ERROR("Failed to allocate proxy terminal");
901 lxc_terminal_delete(terminal
);
905 int lxc_terminal_setup(struct lxc_conf
*conf
)
908 struct lxc_terminal
*terminal
= &conf
->console
;
910 if (terminal
->path
&& strcmp(terminal
->path
, "none") == 0) {
911 INFO("No terminal requested");
915 ret
= lxc_terminal_create(terminal
);
919 ret
= lxc_terminal_create_log_file(terminal
);
923 ret
= lxc_terminal_create_ringbuf(terminal
);
930 lxc_terminal_delete(terminal
);
934 static bool __terminal_dup2(int duplicate
, int original
)
938 if (!isatty(original
))
941 ret
= dup2(duplicate
, original
);
943 SYSERROR("Failed to dup2(%d, %d)", duplicate
, original
);
950 int lxc_terminal_set_stdfds(int fd
)
957 for (i
= 0; i
< 3; i
++)
958 if (!__terminal_dup2(fd
, (int[]){STDIN_FILENO
, STDOUT_FILENO
,
965 int lxc_terminal_stdin_cb(int fd
, uint32_t events
, void *cbdata
,
966 struct lxc_epoll_descr
*descr
)
970 struct lxc_terminal_state
*ts
= cbdata
;
972 if (fd
!= ts
->stdinfd
)
973 return LXC_MAINLOOP_CLOSE
;
975 ret
= lxc_read_nointr(ts
->stdinfd
, &c
, 1);
977 return LXC_MAINLOOP_CLOSE
;
979 if (ts
->escape
>= 1) {
980 /* we want to exit the terminal with Ctrl+a q */
981 if (c
== ts
->escape
&& !ts
->saw_escape
) {
983 return LXC_MAINLOOP_CONTINUE
;
986 if (c
== 'q' && ts
->saw_escape
)
987 return LXC_MAINLOOP_CLOSE
;
992 ret
= lxc_write_nointr(ts
->masterfd
, &c
, 1);
994 return LXC_MAINLOOP_CLOSE
;
996 return LXC_MAINLOOP_CONTINUE
;
999 int lxc_terminal_master_cb(int fd
, uint32_t events
, void *cbdata
,
1000 struct lxc_epoll_descr
*descr
)
1003 char buf
[LXC_TERMINAL_BUFFER_SIZE
];
1004 struct lxc_terminal_state
*ts
= cbdata
;
1006 if (fd
!= ts
->masterfd
)
1007 return LXC_MAINLOOP_CLOSE
;
1009 r
= lxc_read_nointr(fd
, buf
, sizeof(buf
));
1011 return LXC_MAINLOOP_CLOSE
;
1013 w
= lxc_write_nointr(ts
->stdoutfd
, buf
, r
);
1014 if (w
<= 0 || w
!= r
)
1015 return LXC_MAINLOOP_CLOSE
;
1017 return LXC_MAINLOOP_CONTINUE
;
1020 int lxc_terminal_getfd(struct lxc_container
*c
, int *ttynum
, int *masterfd
)
1022 return lxc_cmd_console(c
->name
, ttynum
, masterfd
, c
->config_path
);
1025 int lxc_console(struct lxc_container
*c
, int ttynum
,
1026 int stdinfd
, int stdoutfd
, int stderrfd
,
1029 int ret
, ttyfd
, masterfd
;
1030 struct lxc_epoll_descr descr
;
1031 struct termios oldtios
;
1032 struct lxc_terminal_state
*ts
;
1035 ttyfd
= lxc_cmd_console(c
->name
, &ttynum
, &masterfd
, c
->config_path
);
1041 TRACE("Process is already group leader");
1043 ts
= lxc_terminal_signal_init(stdinfd
, masterfd
);
1048 ts
->escape
= escape
;
1049 ts
->winch_proxy
= c
->name
;
1050 ts
->winch_proxy_lxcpath
= c
->config_path
;
1051 ts
->stdoutfd
= stdoutfd
;
1053 istty
= isatty(stdinfd
);
1055 lxc_terminal_winsz(stdinfd
, masterfd
);
1056 lxc_cmd_terminal_winch(ts
->winch_proxy
, ts
->winch_proxy_lxcpath
);
1058 INFO("File descriptor %d does not refer to a tty device", stdinfd
);
1061 ret
= lxc_mainloop_open(&descr
);
1063 ERROR("Failed to create mainloop");
1067 if (ts
->sigfd
!= -1) {
1068 ret
= lxc_mainloop_add_handler(&descr
, ts
->sigfd
,
1069 lxc_terminal_signalfd_cb
, ts
);
1071 ERROR("Failed to add signal handler to mainloop");
1072 goto close_mainloop
;
1076 ret
= lxc_mainloop_add_handler(&descr
, ts
->stdinfd
,
1077 lxc_terminal_stdin_cb
, ts
);
1079 ERROR("Failed to add stdin handler");
1080 goto close_mainloop
;
1083 ret
= lxc_mainloop_add_handler(&descr
, ts
->masterfd
,
1084 lxc_terminal_master_cb
, ts
);
1086 ERROR("Failed to add master handler");
1087 goto close_mainloop
;
1090 if (ts
->escape
>= 1) {
1093 "Connected to tty %1$d\n"
1094 "Type <Ctrl+%2$c q> to exit the console, "
1095 "<Ctrl+%2$c Ctrl+%2$c> to enter Ctrl+%2$c itself\n",
1096 ttynum
, 'a' + escape
- 1);
1100 ret
= lxc_setup_tios(stdinfd
, &oldtios
);
1102 goto close_mainloop
;
1105 ret
= lxc_mainloop(&descr
, -1);
1107 ERROR("The mainloop returned an error");
1115 istty
= tcsetattr(stdinfd
, TCSAFLUSH
, &oldtios
);
1117 WARN("%s - Failed to restore terminal properties",
1122 lxc_mainloop_close(&descr
);
1125 lxc_terminal_signal_fini(ts
);
1134 int lxc_make_controlling_pty(int fd
)
1140 ret
= ioctl(fd
, TIOCSCTTY
, (char *)NULL
);
1147 int lxc_login_pty(int fd
)
1151 ret
= lxc_make_controlling_pty(fd
);
1155 ret
= lxc_terminal_set_stdfds(fd
);
1159 if (fd
> STDERR_FILENO
)
1165 void lxc_terminal_info_init(struct lxc_terminal_info
*pty
)
1167 pty
->name
[0] = '\0';
1168 pty
->master
= -EBADF
;
1169 pty
->slave
= -EBADF
;
1173 void lxc_terminal_init(struct lxc_terminal
*pty
)
1175 memset(pty
, 0, sizeof(*pty
));
1176 pty
->slave
= -EBADF
;
1177 pty
->master
= -EBADF
;
1179 pty
->log_fd
= -EBADF
;
1180 lxc_terminal_info_init(&pty
->proxy
);
1183 void lxc_terminal_conf_free(struct lxc_terminal
*terminal
)
1185 free(terminal
->log_path
);
1186 free(terminal
->path
);
1187 if (terminal
->buffer_size
> 0 && terminal
->ringbuf
.addr
)
1188 lxc_ringbuf_release(&terminal
->ringbuf
);
1191 int lxc_terminal_map_ids(struct lxc_conf
*c
, struct lxc_terminal
*pty
)
1195 if (lxc_list_empty(&c
->id_map
))
1198 ret
= strcmp(pty
->name
, "");
1202 ret
= chown_mapped_root(pty
->name
, c
);
1204 ERROR("Failed to chown \"%s\"", pty
->name
);
1208 TRACE("Chowned \"%s\"", pty
->name
);