~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages

« back to all changes in this revision

Viewing changes to src/console.c

Tags: upstream-0.2.2
ImportĀ upstreamĀ versionĀ 0.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * console.c: A dumb serial console client
 
3
 *
 
4
 * Copyright (C) 2007 Red Hat, Inc.
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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
 
19
 *
 
20
 * Daniel Berrange <berrange@redhat.com>
 
21
 */
 
22
 
 
23
#include <stdio.h>
 
24
#include <sys/types.h>
 
25
#include <sys/stat.h>
 
26
#include <fcntl.h>
 
27
#include <termios.h>
 
28
#include <poll.h>
 
29
#include <string.h>
 
30
#include <errno.h>
 
31
#include <unistd.h>
 
32
#include <signal.h>
 
33
 
 
34
#include "console.h"
 
35
#include "internal.h"
 
36
 
 
37
/* ie  Ctrl-]  as per telnet */
 
38
#define CTRL_CLOSE_BRACKET '\35'
 
39
 
 
40
static int got_signal = 0;
 
41
static void do_signal(int sig ATTRIBUTE_UNUSED) {
 
42
    got_signal = 1;
 
43
}
 
44
 
 
45
int vshRunConsole(const char *tty) {
 
46
    int ttyfd, ret = -1;
 
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);
 
53
 
 
54
 
 
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));
 
59
        return -1;
 
60
    }
 
61
 
 
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
 
66
       other bits */
 
67
    if (tcgetattr(STDIN_FILENO, &ttyattr) < 0) {
 
68
        fprintf(stderr, _("unable to get tty attributes: %s\n"),
 
69
                strerror(errno));
 
70
        goto closetty;
 
71
    }
 
72
 
 
73
    rawattr = ttyattr;
 
74
    cfmakeraw(&rawattr);
 
75
 
 
76
    if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) {
 
77
        fprintf(stderr, _("unable to set tty attributes: %s\n"),
 
78
                strerror(errno));
 
79
        goto closetty;
 
80
    }
 
81
 
 
82
 
 
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);
 
92
    got_signal = 0;
 
93
 
 
94
 
 
95
    /* Now lets process STDIN & tty forever.... */
 
96
    for (; !got_signal ;) {
 
97
        unsigned int i;
 
98
        struct pollfd fds[] = {
 
99
            { STDIN_FILENO, POLLIN, 0 },
 
100
            { ttyfd, POLLIN, 0 },
 
101
        };
 
102
 
 
103
        /* Wait for data to be available for reading on
 
104
           STDIN or the tty */
 
105
        if (poll(fds, (sizeof(fds)/sizeof(struct pollfd)), -1) < 0) {
 
106
            if (got_signal)
 
107
                goto cleanup;
 
108
 
 
109
            if (errno == EINTR || errno == EAGAIN)
 
110
                continue;
 
111
 
 
112
            fprintf(stderr, _("failure waiting for I/O: %s\n"),
 
113
                    strerror(errno));
 
114
            goto cleanup;
 
115
        }
 
116
 
 
117
        for (i = 0 ; i < (sizeof(fds)/sizeof(struct pollfd)) ; i++) {
 
118
            if (!fds[i].revents)
 
119
                continue;
 
120
 
 
121
            /* Process incoming data available for read */
 
122
            if (fds[i].revents & POLLIN) {
 
123
                char buf[4096];
 
124
                int got, sent = 0, destfd;
 
125
 
 
126
                if ((got = read(fds[i].fd, buf, sizeof(buf))) < 0) {
 
127
                    fprintf(stderr, _("failure reading input: %s\n"),
 
128
                            strerror(errno));
 
129
                    goto cleanup;
 
130
                }
 
131
 
 
132
                /* Quit if end of file, or we got the Ctrl-] key */
 
133
                if (!got ||
 
134
                    (got == 1 &&
 
135
                     buf[0] == CTRL_CLOSE_BRACKET))
 
136
                    goto done;
 
137
 
 
138
                /* Data from stdin goes to the TTY,
 
139
                   data from the TTY goes to STDOUT */
 
140
                if (fds[i].fd == STDIN_FILENO)
 
141
                    destfd = ttyfd;
 
142
                else
 
143
                    destfd = STDOUT_FILENO;
 
144
 
 
145
                while (sent < got) {
 
146
                    int done;
 
147
                    if ((done = write(destfd, buf + sent, got - sent)) <= 0) {
 
148
                        fprintf(stderr, _("failure writing output: %s\n"),
 
149
                                strerror(errno));
 
150
                        goto cleanup;
 
151
                    }
 
152
                    sent += done;
 
153
                }
 
154
            } else { /* Any other flag from poll is an error condition */
 
155
                goto cleanup;
 
156
            }
 
157
        }
 
158
    }
 
159
 done:
 
160
    ret = 0;
 
161
 
 
162
 cleanup:
 
163
 
 
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);
 
170
 
 
171
    /* Put STDIN back into the (sane?) state we found
 
172
       it in before starting */
 
173
    tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);
 
174
 
 
175
 closetty:
 
176
    close(ttyfd);
 
177
 
 
178
    return ret;
 
179
}
 
180
 
 
181
/*
 
182
 * Local variables:
 
183
 *  indent-tabs-mode: nil
 
184
 *  c-indent-level: 4
 
185
 *  c-basic-offset: 4
 
186
 *  tab-width: 4
 
187
 * End:
 
188
 */