]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/lxc_console.c
From: Daniel Lezcano <daniel.lezcano@free.fr>
[mirror_lxc.git] / src / lxc / lxc_console.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <dlezcano at fr.ibm.com>
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24 #define _GNU_SOURCE
25 #include <stdio.h>
26 #undef _GNU_SOURCE
27 #include <stdlib.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <termios.h>
32 #include <unistd.h>
33 #include <signal.h>
34 #include <libgen.h>
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <sys/poll.h>
39
40 #include "error.h"
41 #include "lxc.h"
42
43 void usage(char *cmd)
44 {
45 fprintf(stderr, "%s <command>\n", basename(cmd));
46 fprintf(stderr, "\t -n <name> : name of the container\n");
47 fprintf(stderr, "\t -t <tty#> : tty number\n");
48 _exit(1);
49 }
50
51 int main(int argc, char *argv[])
52 {
53 char opt;
54 char *name = NULL;
55 int ttynum = 0;
56 int nbargs = 0;
57 int master = -1;
58 int wait4q = 0;
59 int err = LXC_ERROR_INTERNAL;
60 struct termios tios, oldtios;
61
62 while ((opt = getopt(argc, argv, "t:n:")) != -1) {
63 switch (opt) {
64 case 'n':
65 name = optarg;
66 break;
67 case 't':
68 ttynum = atoi(optarg);
69 break;
70 }
71
72 nbargs++;
73 }
74
75 if (!name || !ttynum)
76 usage(argv[0]);
77
78 /* Get current termios */
79 if (tcgetattr(0, &tios)) {
80 lxc_log_error("failed to get current terminal settings");
81 fprintf(stderr, "%s\n", lxc_strerror(err));
82 return 1;
83 }
84
85 oldtios = tios;
86
87 /* Remove the echo characters and signal reception, the echo
88 * will be done below with master proxying */
89 tios.c_iflag &= ~IGNBRK;
90 tios.c_iflag &= BRKINT;
91 tios.c_lflag &= ~(ECHO|ICANON|ISIG);
92 tios.c_cc[VMIN] = 1;
93 tios.c_cc[VTIME] = 0;
94
95 /* Set new attributes */
96 if (tcsetattr(0, TCSAFLUSH, &tios)) {
97 lxc_log_syserror("failed to set new terminal settings");
98 fprintf(stderr, "%s\n", lxc_strerror(err));
99 return 1;
100 }
101
102 err = lxc_console(name, ttynum, &master);
103 if (err) {
104 fprintf(stderr, "%s\n", lxc_strerror(err));
105 goto out;
106 }
107
108 fprintf(stderr, "\nType <Ctrl+a q> to exit the console\n");
109
110 setsid();
111
112 err = 0;
113
114 /* let's proxy the tty */
115 for (;;) {
116 char c;
117 struct pollfd pfd[2] = {
118 { .fd = 0,
119 .events = POLLIN|POLLPRI,
120 .revents = 0 },
121 { .fd = master,
122 .events = POLLIN|POLLPRI,
123 .revents = 0 },
124 };
125
126 if (poll(pfd, 2, -1) < 0) {
127 if (errno == EINTR)
128 continue;
129 lxc_log_syserror("failed to poll");
130 goto out_err;
131 }
132
133 /* read the "stdin" and write that to the master
134 */
135 if (pfd[0].revents & POLLIN) {
136 read(0, &c, 1);
137
138 /* we want to exit the console with Ctrl+a q */
139 if (c == 1) {
140 wait4q = !wait4q;
141 continue;
142 }
143
144 if (c == 'q' && wait4q)
145 goto out;
146
147 wait4q = 0;
148 write(master, &c, 1);
149 }
150
151 /* other side has closed the connection */
152 if (pfd[1].revents & POLLHUP)
153 goto out;
154
155 /* read the master and write to "stdout" */
156 if (pfd[1].revents & POLLIN) {
157 read(master, &c, 1);
158 printf("%c", c);
159 fflush(stdout);
160 }
161 }
162 out:
163 /* Restore previous terminal parameter */
164 tcsetattr(0, TCSAFLUSH, &oldtios);
165
166 /* Return to line it is */
167 printf("\n");
168
169 close(master);
170
171 return err;
172
173 out_err:
174 fprintf(stderr, "%s\n", lxc_strerror(-LXC_ERROR_INTERNAL));
175 err = 1;
176 goto out;
177 }