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