* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+
+#define _GNU_SOURCE
#include <stdio.h>
+#undef _GNU_SOURCE
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <termios.h>
#include <unistd.h>
+#include <signal.h>
+#include <libgen.h>
+#include <sys/param.h>
#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
-#include <lxc/lxc.h>
+#include "error.h"
+#include "lxc.h"
-int main(int argc, char *argv[])
+void usage(char *cmd)
{
- return 0;
+ fprintf(stderr, "%s <command>\n", basename(cmd));
+ fprintf(stderr, "\t -n <name> : name of the container\n");
+ fprintf(stderr, "\t -t <tty#> : tty number\n");
+ _exit(1);
}
+int main(int argc, char *argv[])
+{
+ char opt;
+ char *name = NULL;
+ int ttynum = 0;
+ int nbargs = 0;
+ int master = -1;
+ int wait4q = 0;
+ int err = LXC_ERROR_INTERNAL;
+ struct termios tios, oldtios;
+
+ while ((opt = getopt(argc, argv, "t:n:")) != -1) {
+ switch (opt) {
+ case 'n':
+ name = optarg;
+ break;
+ case 't':
+ ttynum = atoi(optarg);
+ break;
+ }
+
+ nbargs++;
+ }
+
+ if (!name || !ttynum)
+ usage(argv[0]);
+
+ /* Get current termios */
+ if (tcgetattr(0, &tios)) {
+ lxc_log_error("failed to get current terminal settings");
+ fprintf(stderr, "%s\n", lxc_strerror(err));
+ return 1;
+ }
+
+ oldtios = tios;
+
+ /* Remove the echo characters and signal reception, the echo
+ * will be done below with master proxying */
+ tios.c_iflag &= ~IGNBRK;
+ tios.c_iflag &= BRKINT;
+ tios.c_lflag &= ~(ECHO|ICANON|ISIG);
+ tios.c_cc[VMIN] = 1;
+ tios.c_cc[VTIME] = 0;
+
+ /* Set new attributes */
+ if (tcsetattr(0, TCSAFLUSH, &tios)) {
+ lxc_log_syserror("failed to set new terminal settings");
+ fprintf(stderr, "%s\n", lxc_strerror(err));
+ return 1;
+ }
+
+ err = lxc_console(name, ttynum, &master);
+ if (err) {
+ fprintf(stderr, "%s\n", lxc_strerror(err));
+ goto out;
+ }
+
+ fprintf(stderr, "\nType <Ctrl+a q> to exit the console\n");
+
+ setsid();
+
+ err = 0;
+
+ /* let's proxy the tty */
+ for (;;) {
+ char c;
+ struct pollfd pfd[2] = {
+ { .fd = 0,
+ .events = POLLIN|POLLPRI,
+ .revents = 0 },
+ { .fd = master,
+ .events = POLLIN|POLLPRI,
+ .revents = 0 },
+ };
+
+ if (poll(pfd, 2, -1) < 0) {
+ if (errno == EINTR)
+ continue;
+ lxc_log_syserror("failed to poll");
+ goto out_err;
+ }
+
+ /* read the "stdin" and write that to the master
+ */
+ if (pfd[0].revents & POLLIN) {
+ read(0, &c, 1);
+
+ /* we want to exit the console with Ctrl+a q */
+ if (c == 1) {
+ wait4q = !wait4q;
+ continue;
+ }
+
+ if (c == 'q' && wait4q)
+ goto out;
+
+ wait4q = 0;
+ write(master, &c, 1);
+ }
+
+ /* other side has closed the connection */
+ if (pfd[1].revents & POLLHUP)
+ goto out;
+
+ /* read the master and write to "stdout" */
+ if (pfd[1].revents & POLLIN) {
+ read(master, &c, 1);
+ printf("%c", c);
+ fflush(stdout);
+ }
+ }
+out:
+ /* Restore previous terminal parameter */
+ tcsetattr(0, TCSAFLUSH, &oldtios);
+
+ /* Return to line it is */
+ printf("\n");
+
+ close(master);
+
+ return err;
+
+out_err:
+ fprintf(stderr, "%s\n", lxc_strerror(-LXC_ERROR_INTERNAL));
+ err = 1;
+ goto out;
+}