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