]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/terminal.c
clear ONLCR flag for container pty
[mirror_lxc.git] / src / lxc / terminal.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 *
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.
13 *
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.
18 *
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
22 */
23
24 #include <errno.h>
25 #include <fcntl.h>
26 #include <lxc/lxccontainer.h>
27 #include <pthread.h>
28 #include <signal.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <sys/epoll.h>
32 #include <sys/types.h>
33 #include <termios.h>
34 #include <unistd.h>
35
36 #include "af_unix.h"
37 #include "caps.h"
38 #include "commands.h"
39 #include "conf.h"
40 #include "config.h"
41 #include "log.h"
42 #include "lxclock.h"
43 #include "mainloop.h"
44 #include "start.h"
45 #include "terminal.h"
46 #include "utils.h"
47
48 #if HAVE_PTY_H
49 #include <pty.h>
50 #else
51 #include <../include/openpty.h>
52 #endif
53
54 #define LXC_TERMINAL_BUFFER_SIZE 1024
55
56 lxc_log_define(terminal, lxc);
57
58 static struct lxc_list lxc_ttys;
59
60 typedef void (*sighandler_t)(int);
61
62 __attribute__((constructor)) void lxc_terminal_init_global(void)
63 {
64 lxc_list_init(&lxc_ttys);
65 }
66
67 void lxc_terminal_winsz(int srcfd, int dstfd)
68 {
69 int ret;
70 struct winsize wsz;
71
72 if (!isatty(srcfd))
73 return;
74
75 ret = ioctl(srcfd, TIOCGWINSZ, &wsz);
76 if (ret < 0) {
77 WARN("Failed to get window size");
78 return;
79 }
80
81 ret = ioctl(dstfd, TIOCSWINSZ, &wsz);
82 if (ret < 0)
83 WARN("Failed to set window size");
84 else
85 DEBUG("Set window size to %d columns and %d rows", wsz.ws_col,
86 wsz.ws_row);
87
88 return;
89 }
90
91 static void lxc_terminal_winch(struct lxc_terminal_state *ts)
92 {
93 lxc_terminal_winsz(ts->stdinfd, ts->masterfd);
94
95 if (ts->winch_proxy)
96 lxc_cmd_terminal_winch(ts->winch_proxy, ts->winch_proxy_lxcpath);
97 }
98
99 void lxc_terminal_sigwinch(int sig)
100 {
101 struct lxc_list *it;
102 struct lxc_terminal_state *ts;
103
104 lxc_list_for_each(it, &lxc_ttys) {
105 ts = it->elem;
106 lxc_terminal_winch(ts);
107 }
108 }
109
110 int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata,
111 struct lxc_epoll_descr *descr)
112 {
113 ssize_t ret;
114 struct signalfd_siginfo siginfo;
115 struct lxc_terminal_state *ts = cbdata;
116
117 ret = read(fd, &siginfo, sizeof(siginfo));
118 if (ret < 0 || (size_t)ret < sizeof(siginfo)) {
119 ERROR("Failed to read signal info");
120 return LXC_MAINLOOP_ERROR;
121 }
122
123 if (siginfo.ssi_signo == SIGTERM) {
124 DEBUG("Received SIGTERM. Detaching from the terminal");
125 return LXC_MAINLOOP_CLOSE;
126 }
127
128 if (siginfo.ssi_signo == SIGWINCH)
129 lxc_terminal_winch(ts);
130
131 return LXC_MAINLOOP_CONTINUE;
132 }
133
134 struct lxc_terminal_state *lxc_terminal_signal_init(int srcfd, int dstfd)
135 {
136 int ret;
137 bool istty = false;
138 sigset_t mask;
139 struct lxc_terminal_state *ts;
140
141 ts = malloc(sizeof(*ts));
142 if (!ts)
143 return NULL;
144
145 memset(ts, 0, sizeof(*ts));
146 ts->stdinfd = srcfd;
147 ts->masterfd = dstfd;
148 ts->sigfd = -1;
149
150 ret = sigemptyset(&mask);
151 if (ret < 0) {
152 SYSERROR("Failed to initialize an empty signal set");
153 goto on_error;
154 }
155
156 istty = (isatty(srcfd) == 1);
157 if (!istty) {
158 INFO("fd %d does not refer to a tty device", srcfd);
159 } else {
160 /* Add tty to list to be scanned at SIGWINCH time. */
161 lxc_list_add_elem(&ts->node, ts);
162 lxc_list_add_tail(&lxc_ttys, &ts->node);
163 ret = sigaddset(&mask, SIGWINCH);
164 if (ret < 0)
165 NOTICE("%s - Failed to add SIGWINCH to signal set",
166 strerror(errno));
167 }
168
169 /* Exit the mainloop cleanly on SIGTERM. */
170 ret = sigaddset(&mask, SIGTERM);
171 if (ret < 0) {
172 SYSERROR("Failed to add SIGWINCH to signal set");
173 goto on_error;
174 }
175
176 ret = pthread_sigmask(SIG_BLOCK, &mask, &ts->oldmask);
177 if (ret < 0) {
178 WARN("Failed to block signals");
179 goto on_error;
180 }
181
182 ts->sigfd = signalfd(-1, &mask, SFD_CLOEXEC);
183 if (ts->sigfd < 0) {
184 WARN("Failed to create signal fd");
185 (void)pthread_sigmask(SIG_SETMASK, &ts->oldmask, NULL);
186 goto on_error;
187 }
188
189 DEBUG("Created signal fd %d", ts->sigfd);
190 return ts;
191
192 on_error:
193 ERROR("Failed to create signal fd");
194 if (ts->sigfd >= 0) {
195 close(ts->sigfd);
196 ts->sigfd = -1;
197 }
198
199 if (istty)
200 lxc_list_del(&ts->node);
201
202 return ts;
203 }
204
205 void lxc_terminal_signal_fini(struct lxc_terminal_state *ts)
206 {
207 if (ts->sigfd >= 0) {
208 close(ts->sigfd);
209
210 if (pthread_sigmask(SIG_SETMASK, &ts->oldmask, NULL) < 0)
211 WARN("%s - Failed to restore signal mask", strerror(errno));
212 }
213
214 if (isatty(ts->stdinfd))
215 lxc_list_del(&ts->node);
216
217 free(ts);
218 }
219
220 static int lxc_terminal_truncate_log_file(struct lxc_terminal *terminal)
221 {
222 /* be very certain things are kosher */
223 if (!terminal->log_path || terminal->log_fd < 0)
224 return -EBADF;
225
226 return lxc_unpriv(ftruncate(terminal->log_fd, 0));
227 }
228
229 static int lxc_terminal_rotate_log_file(struct lxc_terminal *terminal)
230 {
231 int ret;
232 size_t len;
233 char *tmp;
234
235 if (!terminal->log_path || terminal->log_rotate == 0)
236 return -EOPNOTSUPP;
237
238 /* be very certain things are kosher */
239 if (terminal->log_fd < 0)
240 return -EBADF;
241
242 len = strlen(terminal->log_path) + sizeof(".1");
243 tmp = alloca(len);
244
245 ret = snprintf(tmp, len, "%s.1", terminal->log_path);
246 if (ret < 0 || (size_t)ret >= len)
247 return -EFBIG;
248
249 close(terminal->log_fd);
250 terminal->log_fd = -1;
251 ret = lxc_unpriv(rename(terminal->log_path, tmp));
252 if (ret < 0)
253 return ret;
254
255 return lxc_terminal_create_log_file(terminal);
256 }
257
258 static int lxc_terminal_write_log_file(struct lxc_terminal *terminal, char *buf,
259 int bytes_read)
260 {
261 int ret;
262 struct stat st;
263 int64_t space_left = -1;
264
265 if (terminal->log_fd < 0)
266 return 0;
267
268 /* A log size <= 0 means that there's no limit on the size of the log
269 * file at which point we simply ignore whether the log is supposed to
270 * be rotated or not.
271 */
272 if (terminal->log_size <= 0)
273 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
274
275 /* Get current size of the log file. */
276 ret = fstat(terminal->log_fd, &st);
277 if (ret < 0) {
278 SYSERROR("Failed to stat the terminal log file descriptor");
279 return -1;
280 }
281
282 /* handle non-regular files */
283 if ((st.st_mode & S_IFMT) != S_IFREG) {
284 /* This isn't a regular file. so rotating the file seems a
285 * dangerous thing to do, size limits are also very
286 * questionable. Let's not risk anything and tell the user that
287 * he's requesting us to do weird stuff.
288 */
289 if (terminal->log_rotate > 0 || terminal->log_size > 0)
290 return -EINVAL;
291
292 /* I mean, sure log wherever you want to. */
293 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
294 }
295
296 space_left = terminal->log_size - st.st_size;
297
298 /* User doesn't want to rotate the log file and there's no more space
299 * left so simply truncate it.
300 */
301 if (space_left <= 0 && terminal->log_rotate <= 0) {
302 ret = lxc_terminal_truncate_log_file(terminal);
303 if (ret < 0)
304 return ret;
305
306 if (bytes_read <= terminal->log_size)
307 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
308
309 /* Write as much as we can into the buffer and loose the rest. */
310 return lxc_write_nointr(terminal->log_fd, buf, terminal->log_size);
311 }
312
313 /* There's enough space left. */
314 if (bytes_read <= space_left)
315 return lxc_write_nointr(terminal->log_fd, buf, bytes_read);
316
317 /* There's not enough space left but at least write as much as we can
318 * into the old log file.
319 */
320 ret = lxc_write_nointr(terminal->log_fd, buf, space_left);
321 if (ret < 0)
322 return -1;
323
324 /* Calculate how many bytes we still need to write. */
325 bytes_read -= space_left;
326
327 /* There'd be more to write but we aren't instructed to rotate the log
328 * file so simply return. There's no error on our side here.
329 */
330 if (terminal->log_rotate > 0)
331 ret = lxc_terminal_rotate_log_file(terminal);
332 else
333 ret = lxc_terminal_truncate_log_file(terminal);
334 if (ret < 0)
335 return ret;
336
337 if (terminal->log_size < bytes_read) {
338 /* Well, this is unfortunate because it means that there is more
339 * to write than the user has granted us space. There are
340 * multiple ways to handle this but let's use the simplest one:
341 * write as much as we can, tell the user that there was more
342 * stuff to write and move on.
343 * Note that this scenario shouldn't actually happen with the
344 * standard pty-based terminal that LXC allocates since it will
345 * be switched into raw mode. In raw mode only 1 byte at a time
346 * should be read and written.
347 */
348 WARN("Size of terminal log file is smaller than the bytes to write");
349 ret = lxc_write_nointr(terminal->log_fd, buf, terminal->log_size);
350 if (ret < 0)
351 return -1;
352 bytes_read -= ret;
353 return bytes_read;
354 }
355
356 /* Yay, we made it. */
357 ret = lxc_write_nointr(terminal->log_fd, buf, bytes_read);
358 if (ret < 0)
359 return -1;
360 bytes_read -= ret;
361 return bytes_read;
362 }
363
364 int lxc_terminal_io_cb(int fd, uint32_t events, void *data,
365 struct lxc_epoll_descr *descr)
366 {
367 struct lxc_terminal *terminal = data;
368 char buf[LXC_TERMINAL_BUFFER_SIZE];
369 int r, w, w_log, w_rbuf;
370
371 w = r = lxc_read_nointr(fd, buf, sizeof(buf));
372 if (r <= 0) {
373 INFO("Terminal client on fd %d has exited", fd);
374 lxc_mainloop_del_handler(descr, fd);
375
376 if (fd == terminal->master) {
377 terminal->master = -EBADF;
378 } else if (fd == terminal->peer) {
379 if (terminal->tty_state) {
380 lxc_terminal_signal_fini(terminal->tty_state);
381 terminal->tty_state = NULL;
382 }
383 terminal->peer = -EBADF;
384 } else {
385 ERROR("Handler received unexpected file descriptor");
386 }
387 close(fd);
388
389 return LXC_MAINLOOP_CLOSE;
390 }
391
392 if (fd == terminal->peer)
393 w = lxc_write_nointr(terminal->master, buf, r);
394
395 w_rbuf = w_log = 0;
396 if (fd == terminal->master) {
397 /* write to peer first */
398 if (terminal->peer >= 0)
399 w = lxc_write_nointr(terminal->peer, buf, r);
400
401 /* write to terminal ringbuffer */
402 if (terminal->buffer_size > 0)
403 w_rbuf = lxc_ringbuf_write(&terminal->ringbuf, buf, r);
404
405 /* write to terminal log */
406 if (terminal->log_fd >= 0)
407 w_log = lxc_terminal_write_log_file(terminal, buf, r);
408 }
409
410 if (w != r)
411 WARN("Short write on terminal r:%d != w:%d", r, w);
412
413 if (w_rbuf < 0)
414 TRACE("%s - Failed to write %d bytes to terminal ringbuffer",
415 strerror(-w_rbuf), r);
416
417 if (w_log < 0)
418 TRACE("Failed to write %d bytes to terminal log", r);
419
420 return LXC_MAINLOOP_CONTINUE;
421 }
422
423 static int lxc_terminal_mainloop_add_peer(struct lxc_terminal *terminal)
424 {
425 int ret;
426
427 if (terminal->peer >= 0) {
428 ret = lxc_mainloop_add_handler(terminal->descr, terminal->peer,
429 lxc_terminal_io_cb, terminal);
430 if (ret < 0) {
431 WARN("Failed to add terminal peer handler to mainloop");
432 return -1;
433 }
434 }
435
436 if (!terminal->tty_state || terminal->tty_state->sigfd < 0)
437 return 0;
438
439 ret = lxc_mainloop_add_handler(terminal->descr, terminal->tty_state->sigfd,
440 lxc_terminal_signalfd_cb, terminal->tty_state);
441 if (ret < 0) {
442 WARN("Failed to add signal handler to mainloop");
443 return -1;
444 }
445
446 return 0;
447 }
448
449 int lxc_terminal_mainloop_add(struct lxc_epoll_descr *descr,
450 struct lxc_terminal *terminal)
451 {
452 int ret;
453
454 if (terminal->master < 0) {
455 INFO("Terminal is not initialized");
456 return 0;
457 }
458
459 ret = lxc_mainloop_add_handler(descr, terminal->master,
460 lxc_terminal_io_cb, terminal);
461 if (ret < 0) {
462 ERROR("Failed to add handler for terminal master fd %d to "
463 "mainloop", terminal->master);
464 return -1;
465 }
466
467 /* We cache the descr so that we can add an fd to it when someone
468 * does attach to it in lxc_terminal_allocate().
469 */
470 terminal->descr = descr;
471
472 return lxc_terminal_mainloop_add_peer(terminal);
473 }
474
475 int lxc_setup_tios(int fd, struct termios *oldtios)
476 {
477 int ret;
478 struct termios newtios;
479
480 if (!isatty(fd)) {
481 ERROR("File descriptor %d does not refert to a terminal", fd);
482 return -1;
483 }
484
485 /* Get current termios. */
486 ret = tcgetattr(fd, oldtios);
487 if (ret < 0) {
488 SYSERROR("Failed to get current terminal settings");
489 return -1;
490 }
491
492 /* ensure we don't end up in an endless loop:
493 * The kernel might fire SIGTTOU while an
494 * ioctl() in tcsetattr() is executed. When the ioctl()
495 * is resumed and retries, the signal handler interrupts it again.
496 */
497 signal (SIGTTIN, SIG_IGN);
498 signal (SIGTTOU, SIG_IGN);
499
500 newtios = *oldtios;
501
502 /* We use the same settings that ssh does. */
503 newtios.c_iflag |= IGNPAR;
504 newtios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF);
505 #ifdef IUCLC
506 newtios.c_iflag &= ~IUCLC;
507 #endif
508 newtios.c_lflag &= ~(TOSTOP | ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
509 #ifdef IEXTEN
510 newtios.c_lflag &= ~IEXTEN;
511 #endif
512 newtios.c_oflag &= ~ONLCR;
513 newtios.c_oflag |= OPOST;
514 newtios.c_cc[VMIN] = 1;
515 newtios.c_cc[VTIME] = 0;
516
517 /* Set new attributes. */
518 ret = tcsetattr(fd, TCSAFLUSH, &newtios);
519 if (ret < 0) {
520 ERROR("Failed to set new terminal settings");
521 return -1;
522 }
523
524 return 0;
525 }
526
527 static void lxc_terminal_peer_proxy_free(struct lxc_terminal *terminal)
528 {
529 if (terminal->tty_state) {
530 lxc_terminal_signal_fini(terminal->tty_state);
531 terminal->tty_state = NULL;
532 }
533
534 close(terminal->proxy.master);
535 terminal->proxy.master = -1;
536
537 close(terminal->proxy.slave);
538 terminal->proxy.slave = -1;
539
540 terminal->proxy.busy = -1;
541
542 terminal->proxy.name[0] = '\0';
543
544 terminal->peer = -1;
545 }
546
547 static int lxc_terminal_peer_proxy_alloc(struct lxc_terminal *terminal,
548 int sockfd)
549 {
550 int ret;
551 struct termios oldtermio;
552 struct lxc_terminal_state *ts;
553
554 if (terminal->master < 0) {
555 ERROR("Terminal not set up");
556 return -1;
557 }
558
559 if (terminal->proxy.busy != -1 || terminal->peer != -1) {
560 NOTICE("Terminal already in use");
561 return -1;
562 }
563
564 if (terminal->tty_state) {
565 ERROR("Terminal has already been initialized");
566 return -1;
567 }
568
569 /* This is the proxy terminal that will be given to the client, and
570 * that the real terminal master will send to / recv from.
571 */
572 ret = openpty(&terminal->proxy.master, &terminal->proxy.slave,
573 terminal->proxy.name, NULL, NULL);
574 if (ret < 0) {
575 SYSERROR("Failed to open proxy terminal");
576 return -1;
577 }
578
579 ret = lxc_setup_tios(terminal->proxy.slave, &oldtermio);
580 if (ret < 0)
581 goto on_error;
582
583 ts = lxc_terminal_signal_init(terminal->proxy.master, terminal->master);
584 if (!ts)
585 goto on_error;
586
587 terminal->tty_state = ts;
588 terminal->peer = terminal->proxy.slave;
589 terminal->proxy.busy = sockfd;
590 ret = lxc_terminal_mainloop_add_peer(terminal);
591 if (ret < 0)
592 goto on_error;
593
594 NOTICE("Opened proxy terminal with master fd %d and slave fd %d",
595 terminal->proxy.master, terminal->proxy.slave);
596 return 0;
597
598 on_error:
599 lxc_terminal_peer_proxy_free(terminal);
600 return -1;
601 }
602
603 int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttyreq)
604 {
605 int ttynum;
606 int masterfd = -1;
607 struct lxc_tty_info *ttys = &conf->ttys;
608 struct lxc_terminal *terminal = &conf->console;
609
610 if (*ttyreq == 0) {
611 int ret;
612
613 ret = lxc_terminal_peer_proxy_alloc(terminal, sockfd);
614 if (ret < 0)
615 goto out;
616
617 masterfd = terminal->proxy.master;
618 goto out;
619 }
620
621 if (*ttyreq > 0) {
622 if (*ttyreq > ttys->max)
623 goto out;
624
625 if (ttys->tty[*ttyreq - 1].busy)
626 goto out;
627
628 /* The requested tty is available. */
629 ttynum = *ttyreq;
630 goto out_tty;
631 }
632
633 /* Search for next available tty, fixup index tty1 => [0]. */
634 for (ttynum = 1; ttynum <= ttys->max && ttys->tty[ttynum - 1].busy; ttynum++) {
635 ;
636 }
637
638 /* We didn't find any available slot for tty. */
639 if (ttynum > ttys->max)
640 goto out;
641
642 *ttyreq = ttynum;
643
644 out_tty:
645 ttys->tty[ttynum - 1].busy = sockfd;
646 masterfd = ttys->tty[ttynum - 1].master;
647
648 out:
649 return masterfd;
650 }
651
652 void lxc_terminal_free(struct lxc_conf *conf, int fd)
653 {
654 int i;
655 struct lxc_tty_info *ttys = &conf->ttys;
656 struct lxc_terminal *terminal = &conf->console;
657
658 for (i = 0; i < ttys->max; i++)
659 if (ttys->tty[i].busy == fd)
660 ttys->tty[i].busy = 0;
661
662 if (terminal->proxy.busy != fd)
663 return;
664
665 lxc_mainloop_del_handler(terminal->descr, terminal->proxy.slave);
666 lxc_terminal_peer_proxy_free(terminal);
667 }
668
669 static int lxc_terminal_peer_default(struct lxc_terminal *terminal)
670 {
671 struct lxc_terminal_state *ts;
672 const char *path;
673 int ret = 0;
674
675 if (terminal->path)
676 path = terminal->path;
677 else
678 path = "/dev/tty";
679
680 terminal->peer = lxc_unpriv(open(path, O_RDWR | O_CLOEXEC));
681 if (terminal->peer < 0) {
682 if (!terminal->path) {
683 errno = ENODEV;
684 DEBUG("%s - The process does not have a controlling "
685 "terminal", strerror(errno));
686 goto on_succes;
687 }
688
689 ERROR("%s - Failed to open proxy terminal \"%s\"",
690 strerror(errno), path);
691 return -ENOTTY;
692 }
693 DEBUG("Using terminal \"%s\" as proxy", path);
694
695 if (!isatty(terminal->peer)) {
696 ERROR("File descriptor for \"%s\" does not refer to a terminal", path);
697 goto on_error_free_tios;
698 }
699
700 ts = lxc_terminal_signal_init(terminal->peer, terminal->master);
701 terminal->tty_state = ts;
702 if (!ts) {
703 WARN("Failed to install signal handler");
704 goto on_error_free_tios;
705 }
706
707 lxc_terminal_winsz(terminal->peer, terminal->master);
708
709 terminal->tios = malloc(sizeof(*terminal->tios));
710 if (!terminal->tios)
711 goto on_error_free_tios;
712
713 ret = lxc_setup_tios(terminal->peer, terminal->tios);
714 if (ret < 0)
715 goto on_error_close_peer;
716 else
717 goto on_succes;
718
719 on_error_free_tios:
720 free(terminal->tios);
721 terminal->tios = NULL;
722
723 on_error_close_peer:
724 close(terminal->peer);
725 terminal->peer = -1;
726 ret = -ENOTTY;
727
728 on_succes:
729 return ret;
730 }
731
732 int lxc_terminal_write_ringbuffer(struct lxc_terminal *terminal)
733 {
734 char *r_addr;
735 ssize_t ret;
736 uint64_t used;
737 struct lxc_ringbuf *buf = &terminal->ringbuf;
738
739 /* There's not log file where we can dump the ringbuffer to. */
740 if (terminal->log_fd < 0)
741 return 0;
742
743 used = lxc_ringbuf_used(buf);
744 if (used == 0)
745 return 0;
746
747 ret = lxc_terminal_truncate_log_file(terminal);
748 if (ret < 0)
749 return ret;
750
751 /* Write as much as we can without exceeding the limit. */
752 if (terminal->log_size < used)
753 used = terminal->log_size;
754
755 r_addr = lxc_ringbuf_get_read_addr(buf);
756 ret = lxc_write_nointr(terminal->log_fd, r_addr, used);
757 if (ret < 0)
758 return -EIO;
759
760 return 0;
761 }
762
763 void lxc_terminal_delete(struct lxc_terminal *terminal)
764 {
765 int ret;
766
767 ret = lxc_terminal_write_ringbuffer(terminal);
768 if (ret < 0)
769 WARN("Failed to write terminal log to disk");
770
771 if (terminal->tios && terminal->peer >= 0) {
772 ret = tcsetattr(terminal->peer, TCSAFLUSH, terminal->tios);
773 if (ret < 0)
774 WARN("%s - Failed to set old terminal settings", strerror(errno));
775 }
776 free(terminal->tios);
777 terminal->tios = NULL;
778
779 if (terminal->peer >= 0)
780 close(terminal->peer);
781 terminal->peer = -1;
782
783 if (terminal->master >= 0)
784 close(terminal->master);
785 terminal->master = -1;
786
787 if (terminal->slave >= 0)
788 close(terminal->slave);
789 terminal->slave = -1;
790
791 if (terminal->log_fd >= 0)
792 close(terminal->log_fd);
793 terminal->log_fd = -1;
794 }
795
796 /**
797 * Note that this function needs to run before the mainloop starts. Since we
798 * register a handler for the terminal's masterfd when we create the mainloop
799 * the terminal handler needs to see an allocated ringbuffer.
800 */
801 static int lxc_terminal_create_ringbuf(struct lxc_terminal *terminal)
802 {
803 int ret;
804 struct lxc_ringbuf *buf = &terminal->ringbuf;
805 uint64_t size = terminal->buffer_size;
806
807 /* no ringbuffer previously allocated and no ringbuffer requested */
808 if (!buf->addr && size <= 0)
809 return 0;
810
811 /* ringbuffer allocated but no new ringbuffer requested */
812 if (buf->addr && size <= 0) {
813 lxc_ringbuf_release(buf);
814 buf->addr = NULL;
815 buf->r_off = 0;
816 buf->w_off = 0;
817 buf->size = 0;
818 TRACE("Deallocated terminal ringbuffer");
819 return 0;
820 }
821
822 if (size <= 0)
823 return 0;
824
825 /* check wether the requested size for the ringbuffer has changed */
826 if (buf->addr && buf->size != size) {
827 TRACE("Terminal ringbuffer size changed from %" PRIu64
828 " to %" PRIu64 " bytes. Deallocating terminal ringbuffer",
829 buf->size, size);
830 lxc_ringbuf_release(buf);
831 }
832
833 ret = lxc_ringbuf_create(buf, size);
834 if (ret < 0) {
835 ERROR("Failed to setup %" PRIu64 " byte terminal ringbuffer", size);
836 return -1;
837 }
838
839 TRACE("Allocated %" PRIu64 " byte terminal ringbuffer", size);
840 return 0;
841 }
842
843 /**
844 * This is the terminal log file. Please note that the terminal log file is
845 * (implementation wise not content wise) independent of the terminal ringbuffer.
846 */
847 int lxc_terminal_create_log_file(struct lxc_terminal *terminal)
848 {
849 if (!terminal->log_path)
850 return 0;
851
852 terminal->log_fd = lxc_unpriv(open(terminal->log_path, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600));
853 if (terminal->log_fd < 0) {
854 SYSERROR("Failed to open terminal log file \"%s\"", terminal->log_path);
855 return -1;
856 }
857
858 DEBUG("Using \"%s\" as terminal log file", terminal->log_path);
859 return 0;
860 }
861
862 int lxc_terminal_create(struct lxc_terminal *terminal)
863 {
864 int ret;
865
866 ret = openpty(&terminal->master, &terminal->slave, terminal->name, NULL, NULL);
867 if (ret < 0) {
868 SYSERROR("Failed to open terminal");
869 return -1;
870 }
871
872 ret = fcntl(terminal->master, F_SETFD, FD_CLOEXEC);
873 if (ret < 0) {
874 SYSERROR("Failed to set FD_CLOEXEC flag on terminal master");
875 goto err;
876 }
877
878 ret = fcntl(terminal->slave, F_SETFD, FD_CLOEXEC);
879 if (ret < 0) {
880 SYSERROR("Failed to set FD_CLOEXEC flag on terminal slave");
881 goto err;
882 }
883
884 ret = lxc_terminal_peer_default(terminal);
885 if (ret < 0) {
886 ERROR("Failed to allocate proxy terminal");
887 goto err;
888 }
889
890 return 0;
891
892 err:
893 lxc_terminal_delete(terminal);
894 return -ENODEV;
895 }
896
897 int lxc_terminal_setup(struct lxc_conf *conf)
898 {
899 int ret;
900 struct lxc_terminal *terminal = &conf->console;
901 struct termios oldtios;
902
903 if (terminal->path && strcmp(terminal->path, "none") == 0) {
904 INFO("No terminal requested");
905 return 0;
906 }
907
908 ret = lxc_terminal_create(terminal);
909 if (ret < 0)
910 return -1;
911
912 ret = lxc_setup_tios(terminal->master, &oldtios);
913 if (ret < 0)
914 return -1;
915
916 ret = lxc_terminal_create_log_file(terminal);
917 if (ret < 0)
918 goto err;
919
920 ret = lxc_terminal_create_ringbuf(terminal);
921 if (ret < 0)
922 goto err;
923
924 return 0;
925
926 err:
927 lxc_terminal_delete(terminal);
928 return -ENODEV;
929 }
930
931 static bool __terminal_dup2(int duplicate, int original)
932 {
933 int ret;
934
935 if (!isatty(original))
936 return true;
937
938 ret = dup2(duplicate, original);
939 if (ret < 0) {
940 SYSERROR("Failed to dup2(%d, %d)", duplicate, original);
941 return false;
942 }
943
944 return true;
945 }
946
947 int lxc_terminal_set_stdfds(int fd)
948 {
949 int i;
950
951 if (fd < 0)
952 return 0;
953
954 for (i = 0; i < 3; i++)
955 if (!__terminal_dup2(fd, (int[]){STDIN_FILENO, STDOUT_FILENO,
956 STDERR_FILENO}[i]))
957 return -1;
958
959 return 0;
960 }
961
962 int lxc_terminal_stdin_cb(int fd, uint32_t events, void *cbdata,
963 struct lxc_epoll_descr *descr)
964 {
965 int ret;
966 char c;
967 struct lxc_terminal_state *ts = cbdata;
968
969 if (fd != ts->stdinfd)
970 return LXC_MAINLOOP_CLOSE;
971
972 ret = lxc_read_nointr(ts->stdinfd, &c, 1);
973 if (ret <= 0)
974 return LXC_MAINLOOP_CLOSE;
975
976 if (ts->escape >= 1) {
977 /* we want to exit the terminal with Ctrl+a q */
978 if (c == ts->escape && !ts->saw_escape) {
979 ts->saw_escape = 1;
980 return LXC_MAINLOOP_CONTINUE;
981 }
982
983 if (c == 'q' && ts->saw_escape)
984 return LXC_MAINLOOP_CLOSE;
985
986 ts->saw_escape = 0;
987 }
988
989 ret = lxc_write_nointr(ts->masterfd, &c, 1);
990 if (ret <= 0)
991 return LXC_MAINLOOP_CLOSE;
992
993 return LXC_MAINLOOP_CONTINUE;
994 }
995
996 int lxc_terminal_master_cb(int fd, uint32_t events, void *cbdata,
997 struct lxc_epoll_descr *descr)
998 {
999 int r, w;
1000 char buf[LXC_TERMINAL_BUFFER_SIZE];
1001 struct lxc_terminal_state *ts = cbdata;
1002
1003 if (fd != ts->masterfd)
1004 return LXC_MAINLOOP_CLOSE;
1005
1006 r = lxc_read_nointr(fd, buf, sizeof(buf));
1007 if (r <= 0)
1008 return LXC_MAINLOOP_CLOSE;
1009
1010 w = lxc_write_nointr(ts->stdoutfd, buf, r);
1011 if (w <= 0 || w != r)
1012 return LXC_MAINLOOP_CLOSE;
1013
1014 return LXC_MAINLOOP_CONTINUE;
1015 }
1016
1017 int lxc_terminal_getfd(struct lxc_container *c, int *ttynum, int *masterfd)
1018 {
1019 return lxc_cmd_console(c->name, ttynum, masterfd, c->config_path);
1020 }
1021
1022 int lxc_console(struct lxc_container *c, int ttynum,
1023 int stdinfd, int stdoutfd, int stderrfd,
1024 int escape)
1025 {
1026 int masterfd, ret, ttyfd;
1027 struct lxc_epoll_descr descr;
1028 struct termios oldtios;
1029 struct lxc_terminal_state *ts;
1030 int istty = 0;
1031
1032 ttyfd = lxc_cmd_console(c->name, &ttynum, &masterfd, c->config_path);
1033 if (ttyfd < 0)
1034 return -1;
1035
1036 ret = setsid();
1037 if (ret < 0)
1038 TRACE("Process is already group leader");
1039
1040 ts = lxc_terminal_signal_init(stdinfd, masterfd);
1041 if (!ts) {
1042 ret = -1;
1043 goto close_fds;
1044 }
1045 ts->escape = escape;
1046 ts->winch_proxy = c->name;
1047 ts->winch_proxy_lxcpath = c->config_path;
1048 ts->stdoutfd = stdoutfd;
1049
1050 istty = isatty(stdinfd);
1051 if (istty) {
1052 lxc_terminal_winsz(stdinfd, masterfd);
1053 lxc_cmd_terminal_winch(ts->winch_proxy, ts->winch_proxy_lxcpath);
1054 } else {
1055 INFO("File descriptor %d does not refer to a terminal", stdinfd);
1056 }
1057
1058 ret = lxc_mainloop_open(&descr);
1059 if (ret) {
1060 ERROR("Failed to create mainloop");
1061 goto sigwinch_fini;
1062 }
1063
1064 if (ts->sigfd != -1) {
1065 ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
1066 lxc_terminal_signalfd_cb, ts);
1067 if (ret < 0) {
1068 ERROR("Failed to add signal handler to mainloop");
1069 goto close_mainloop;
1070 }
1071 }
1072
1073 ret = lxc_mainloop_add_handler(&descr, ts->stdinfd,
1074 lxc_terminal_stdin_cb, ts);
1075 if (ret < 0) {
1076 ERROR("Failed to add stdin handler");
1077 goto close_mainloop;
1078 }
1079
1080 ret = lxc_mainloop_add_handler(&descr, ts->masterfd,
1081 lxc_terminal_master_cb, ts);
1082 if (ret < 0) {
1083 ERROR("Failed to add master handler");
1084 goto close_mainloop;
1085 }
1086
1087 if (ts->escape >= 1) {
1088 fprintf(stderr,
1089 "\n"
1090 "Connected to tty %1$d\n"
1091 "Type <Ctrl+%2$c q> to exit the console, "
1092 "<Ctrl+%2$c Ctrl+%2$c> to enter Ctrl+%2$c itself\n",
1093 ttynum, 'a' + escape - 1);
1094 }
1095
1096 if (istty) {
1097 ret = lxc_setup_tios(stdinfd, &oldtios);
1098 if (ret < 0)
1099 goto close_mainloop;
1100 }
1101
1102 ret = lxc_mainloop(&descr, -1);
1103 if (ret < 0) {
1104 ERROR("The mainloop returned an error");
1105 goto restore_tios;
1106 }
1107
1108 ret = 0;
1109
1110 restore_tios:
1111 if (istty) {
1112 istty = tcsetattr(stdinfd, TCSAFLUSH, &oldtios);
1113 if (istty < 0)
1114 WARN("%s - Failed to restore terminal properties",
1115 strerror(errno));
1116 }
1117
1118 close_mainloop:
1119 lxc_mainloop_close(&descr);
1120
1121 sigwinch_fini:
1122 lxc_terminal_signal_fini(ts);
1123
1124 close_fds:
1125 close(masterfd);
1126 close(ttyfd);
1127
1128 return ret;
1129 }
1130
1131 int lxc_make_controlling_terminal(int fd)
1132 {
1133 int ret;
1134
1135 setsid();
1136
1137 ret = ioctl(fd, TIOCSCTTY, (char *)NULL);
1138 if (ret < 0)
1139 return -1;
1140
1141 return 0;
1142 }
1143
1144 int lxc_terminal_prepare_login(int fd)
1145 {
1146 int ret;
1147
1148 ret = lxc_make_controlling_terminal(fd);
1149 if (ret < 0)
1150 return -1;
1151
1152 ret = lxc_terminal_set_stdfds(fd);
1153 if (ret < 0)
1154 return -1;
1155
1156 if (fd > STDERR_FILENO)
1157 close(fd);
1158
1159 return 0;
1160 }
1161
1162 void lxc_terminal_info_init(struct lxc_terminal_info *terminal)
1163 {
1164 terminal->name[0] = '\0';
1165 terminal->master = -EBADF;
1166 terminal->slave = -EBADF;
1167 terminal->busy = -1;
1168 }
1169
1170 void lxc_terminal_init(struct lxc_terminal *terminal)
1171 {
1172 memset(terminal, 0, sizeof(*terminal));
1173 terminal->slave = -EBADF;
1174 terminal->master = -EBADF;
1175 terminal->peer = -EBADF;
1176 terminal->log_fd = -EBADF;
1177 lxc_terminal_info_init(&terminal->proxy);
1178 }
1179
1180 void lxc_terminal_conf_free(struct lxc_terminal *terminal)
1181 {
1182 free(terminal->log_path);
1183 free(terminal->path);
1184 if (terminal->buffer_size > 0 && terminal->ringbuf.addr)
1185 lxc_ringbuf_release(&terminal->ringbuf);
1186 }
1187
1188 int lxc_terminal_map_ids(struct lxc_conf *c, struct lxc_terminal *terminal)
1189 {
1190 int ret;
1191
1192 if (lxc_list_empty(&c->id_map))
1193 return 0;
1194
1195 if (strcmp(terminal->name, "") == 0)
1196 return 0;
1197
1198 ret = chown_mapped_root(terminal->name, c);
1199 if (ret < 0) {
1200 ERROR("Failed to chown terminal \"%s\"", terminal->name);
1201 return -1;
1202 }
1203
1204 TRACE("Chowned terminal \"%s\"", terminal->name);
1205
1206 return 0;
1207 }