2
* console.c: A dumb serial console client
4
* Copyright (C) 2007 Red Hat, Inc.
6
* This library is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU Lesser General Public
8
* License as published by the Free Software Foundation; either
9
* version 2.1 of the License, or (at your option) any later version.
11
* This library is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
* Lesser General Public License for more details.
16
* You should have received a copy of the GNU Lesser General Public
17
* License along with this library; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
* Daniel Berrange <berrange@redhat.com>
24
#include <sys/types.h>
37
/* ie Ctrl-] as per telnet */
38
#define CTRL_CLOSE_BRACKET '\35'
40
static int got_signal = 0;
41
static void do_signal(int sig ATTRIBUTE_UNUSED) {
45
int vshRunConsole(const char *tty) {
47
struct termios ttyattr, rawattr;
48
void (*old_sigquit)(int);
49
void (*old_sigterm)(int);
50
void (*old_sigint)(int);
51
void (*old_sighup)(int);
52
void (*old_sigpipe)(int);
55
/* We do not want this to become the controlling TTY */
56
if ((ttyfd = open(tty, O_NOCTTY | O_RDWR)) < 0) {
57
fprintf(stderr, _("unable to open tty %s: %s\n"),
58
tty, strerror(errno));
62
/* Put STDIN into raw mode so that stuff typed
63
does not echo to the screen (the TTY reads will
64
result in it being echoed back already), and
65
also ensure Ctrl-C, etc is blocked, and misc
67
if (tcgetattr(STDIN_FILENO, &ttyattr) < 0) {
68
fprintf(stderr, _("unable to get tty attributes: %s\n"),
76
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) {
77
fprintf(stderr, _("unable to set tty attributes: %s\n"),
83
/* Trap all common signals so that we can safely restore
84
the original terminal settings on STDIN before the
85
process exits - people don't like being left with a
86
messed up terminal ! */
87
old_sigquit = signal(SIGQUIT, do_signal);
88
old_sigterm = signal(SIGTERM, do_signal);
89
old_sigint = signal(SIGINT, do_signal);
90
old_sighup = signal(SIGHUP, do_signal);
91
old_sigpipe = signal(SIGPIPE, do_signal);
95
/* Now lets process STDIN & tty forever.... */
96
for (; !got_signal ;) {
98
struct pollfd fds[] = {
99
{ STDIN_FILENO, POLLIN, 0 },
100
{ ttyfd, POLLIN, 0 },
103
/* Wait for data to be available for reading on
105
if (poll(fds, (sizeof(fds)/sizeof(struct pollfd)), -1) < 0) {
109
if (errno == EINTR || errno == EAGAIN)
112
fprintf(stderr, _("failure waiting for I/O: %s\n"),
117
for (i = 0 ; i < (sizeof(fds)/sizeof(struct pollfd)) ; i++) {
121
/* Process incoming data available for read */
122
if (fds[i].revents & POLLIN) {
124
int got, sent = 0, destfd;
126
if ((got = read(fds[i].fd, buf, sizeof(buf))) < 0) {
127
fprintf(stderr, _("failure reading input: %s\n"),
132
/* Quit if end of file, or we got the Ctrl-] key */
135
buf[0] == CTRL_CLOSE_BRACKET))
138
/* Data from stdin goes to the TTY,
139
data from the TTY goes to STDOUT */
140
if (fds[i].fd == STDIN_FILENO)
143
destfd = STDOUT_FILENO;
147
if ((done = write(destfd, buf + sent, got - sent)) <= 0) {
148
fprintf(stderr, _("failure writing output: %s\n"),
154
} else { /* Any other flag from poll is an error condition */
164
/* Restore original signal handlers */
165
signal(SIGQUIT, old_sigpipe);
166
signal(SIGQUIT, old_sighup);
167
signal(SIGQUIT, old_sigint);
168
signal(SIGQUIT, old_sigterm);
169
signal(SIGQUIT, old_sigquit);
171
/* Put STDIN back into the (sane?) state we found
172
it in before starting */
173
tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);
183
* indent-tabs-mode: nil