ia64/xen-unstable

view tools/console/client/main.c @ 6552:a9873d384da4

Merge.
author adsharma@los-vmm.sc.intel.com
date Thu Aug 25 12:24:48 2005 -0700 (2005-08-25)
parents 112d44270733 fa0754a9f64f
children dfaf788ab18c
line source
1 /*\
2 * Copyright (C) International Business Machines Corp., 2005
3 * Author(s): Anthony Liguori <aliguori@us.ibm.com>
4 *
5 * Xen Console Daemon
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; under version 2 of the License.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 \*/
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <sys/un.h>
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #include <fcntl.h>
30 #include <sys/wait.h>
31 #include <termios.h>
32 #include <signal.h>
33 #include <getopt.h>
34 #include <sys/select.h>
35 #include <err.h>
36 #include <errno.h>
37 #include <pty.h>
39 #include "xenctrl.h"
40 #include "xs.h"
42 #define ESCAPE_CHARACTER 0x1d
44 static volatile sig_atomic_t received_signal = 0;
46 static void sighandler(int signum)
47 {
48 received_signal = 1;
49 }
51 static bool write_sync(int fd, const void *data, size_t size)
52 {
53 size_t offset = 0;
54 ssize_t len;
56 while (offset < size) {
57 len = write(fd, data + offset, size - offset);
58 if (len < 1) {
59 return false;
60 }
61 offset += len;
62 }
64 return true;
65 }
67 static void usage(const char *program) {
68 printf("Usage: %s [OPTION] DOMID\n"
69 "Attaches to a virtual domain console\n"
70 "\n"
71 " -h, --help display this help and exit\n"
72 , program);
73 }
75 /* don't worry too much if setting terminal attributes fail */
76 static void init_term(int fd, struct termios *old)
77 {
78 struct termios new_term;
80 if (tcgetattr(fd, old) == -1) {
81 return;
82 }
84 new_term = *old;
85 cfmakeraw(&new_term);
87 tcsetattr(fd, TCSAFLUSH, &new_term);
88 }
90 static void restore_term(int fd, struct termios *old)
91 {
92 tcsetattr(fd, TCSAFLUSH, old);
93 }
95 static int console_loop(int xc_handle, domid_t domid, int fd)
96 {
97 int ret;
99 do {
100 fd_set fds;
102 FD_ZERO(&fds);
103 FD_SET(STDIN_FILENO, &fds);
104 FD_SET(fd, &fds);
106 ret = select(fd + 1, &fds, NULL, NULL, NULL);
107 if (ret == -1) {
108 if (errno == EINTR || errno == EAGAIN) {
109 continue;
110 }
111 return -1;
112 }
114 if (FD_ISSET(STDIN_FILENO, &fds)) {
115 ssize_t len;
116 char msg[60];
118 len = read(STDIN_FILENO, msg, sizeof(msg));
119 if (len == 1 && msg[0] == ESCAPE_CHARACTER) {
120 return 0;
121 }
123 if (len == 0 || len == -1) {
124 if (len == -1 &&
125 (errno == EINTR || errno == EAGAIN)) {
126 continue;
127 }
128 return -1;
129 }
131 if (!write_sync(fd, msg, len)) {
132 perror("write() failed");
133 return -1;
134 }
135 }
137 if (FD_ISSET(fd, &fds)) {
138 ssize_t len;
139 char msg[512];
141 len = read(fd, msg, sizeof(msg));
142 if (len == 0 || len == -1) {
143 if (len == -1 &&
144 (errno == EINTR || errno == EAGAIN)) {
145 continue;
146 }
147 return -1;
148 }
150 if (!write_sync(STDOUT_FILENO, msg, len)) {
151 perror("write() failed");
152 return -1;
153 }
154 }
155 } while (received_signal == 0);
157 return 0;
158 }
160 int main(int argc, char **argv)
161 {
162 struct termios attr;
163 int domid;
164 int xc_handle;
165 char *sopt = "h";
166 int ch;
167 int opt_ind=0;
168 struct option lopt[] = {
169 { "help", 0, 0, 'h' },
170 { 0 },
172 };
173 char *str_pty;
174 char path[1024];
175 int spty;
176 unsigned int len = 0;
177 struct xs_handle *xs;
178 char *end;
180 while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
181 switch(ch) {
182 case 'h':
183 usage(argv[0]);
184 exit(0);
185 break;
186 }
187 }
189 if ((argc - optind) != 1) {
190 fprintf(stderr, "Invalid number of arguments\n");
191 fprintf(stderr, "Try `%s --help' for more information.\n",
192 argv[0]);
193 exit(EINVAL);
194 }
196 domid = strtol(argv[optind], &end, 10);
197 if (end && *end) {
198 fprintf(stderr, "Invalid DOMID `%s'\n", argv[optind]);
199 fprintf(stderr, "Try `%s --help' for more information.\n",
200 argv[0]);
201 exit(EINVAL);
202 }
204 xs = xs_daemon_open();
205 if (xs == NULL) {
206 err(errno, "Could not contact XenStore");
207 }
209 xc_handle = xc_interface_open();
210 if (xc_handle == -1) {
211 err(errno, "xc_interface_open()");
212 }
214 signal(SIGTERM, sighandler);
216 snprintf(path, sizeof(path), "/console/%d/tty", domid);
217 str_pty = xs_read(xs, path, &len);
218 /* FIXME consoled currently does not assume domain-0 doesn't have a
219 console which is good when we break domain-0 up. To keep us
220 user friendly, we'll bail out here since no data will ever show
221 up on domain-0. */
222 if (domid == 0 || str_pty == NULL) {
223 err(errno, "Could not read tty from store");
224 }
225 spty = open(str_pty, O_RDWR | O_NOCTTY);
226 if (spty == -1) {
227 err(errno, "Could not open tty `%s'", str_pty);
228 }
229 free(str_pty);
231 init_term(STDIN_FILENO, &attr);
232 console_loop(xc_handle, domid, spty);
233 restore_term(STDIN_FILENO, &attr);
235 return 0;
236 }