ia64/xen-unstable

view tools/ioemu/monitor.c @ 6538:84ee014ebd41

Merge xen-vtx-unstable.hg
author adsharma@los-vmm.sc.intel.com
date Wed Aug 17 12:34:38 2005 -0800 (2005-08-17)
parents 23979fb12c49 3f1f7cf07369
children 99914b54f7bf
line source
1 /*
2 * QEMU monitor
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 #include "vl.h"
25 #include <dirent.h>
27 //#define DEBUG
28 //#define DEBUG_COMPLETION
30 #ifndef offsetof
31 #define offsetof(type, field) ((size_t) &((type *)0)->field)
32 #endif
34 /*
35 * Supported types:
36 *
37 * 'F' filename
38 * 'B' block device name
39 * 's' string (accept optional quote)
40 * 'i' integer
41 * '/' optional gdb-like print format (like "/10x")
42 *
43 * '?' optional type (for 'F', 's' and 'i')
44 *
45 */
47 typedef struct term_cmd_t {
48 const char *name;
49 const char *args_type;
50 void (*handler)();
51 const char *params;
52 const char *help;
53 } term_cmd_t;
55 static CharDriverState *monitor_hd;
57 static term_cmd_t term_cmds[];
58 static term_cmd_t info_cmds[];
60 static char term_outbuf[1024];
61 static int term_outbuf_index;
63 static void monitor_start_input(void);
65 void term_flush(void)
66 {
67 if (term_outbuf_index > 0) {
68 if(monitor_hd)
69 qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index);
70 else
71 fwrite(term_outbuf, term_outbuf_index, 1, stderr);
72 term_outbuf_index = 0;
73 }
74 }
76 /* flush at every end of line or if the buffer is full */
77 void term_puts(const char *str)
78 {
79 int c;
80 for(;;) {
81 c = *str++;
82 if (c == '\0')
83 break;
84 term_outbuf[term_outbuf_index++] = c;
85 if (term_outbuf_index >= sizeof(term_outbuf) ||
86 c == '\n')
87 term_flush();
88 }
89 }
91 void term_vprintf(const char *fmt, va_list ap)
92 {
93 char buf[4096];
94 vsnprintf(buf, sizeof(buf), fmt, ap);
95 term_puts(buf);
96 }
98 void term_printf(const char *fmt, ...)
99 {
100 va_list ap;
101 va_start(ap, fmt);
102 term_vprintf(fmt, ap);
103 va_end(ap);
104 }
106 static int compare_cmd(const char *name, const char *list)
107 {
108 const char *p, *pstart;
109 int len;
110 len = strlen(name);
111 p = list;
112 for(;;) {
113 pstart = p;
114 p = strchr(p, '|');
115 if (!p)
116 p = pstart + strlen(pstart);
117 if ((p - pstart) == len && !memcmp(pstart, name, len))
118 return 1;
119 if (*p == '\0')
120 break;
121 p++;
122 }
123 return 0;
124 }
126 static void help_cmd1(term_cmd_t *cmds, const char *prefix, const char *name)
127 {
128 term_cmd_t *cmd;
130 for(cmd = cmds; cmd->name != NULL; cmd++) {
131 if (!name || !strcmp(name, cmd->name))
132 term_printf("%s%s %s -- %s\n", prefix, cmd->name, cmd->params, cmd->help);
133 }
134 }
136 static void help_cmd(const char *name)
137 {
138 if (name && !strcmp(name, "info")) {
139 help_cmd1(info_cmds, "info ", NULL);
140 } else {
141 help_cmd1(term_cmds, "", name);
142 if (name && !strcmp(name, "log")) {
143 CPULogItem *item;
144 term_printf("Log items (comma separated):\n");
145 term_printf("%-10s %s\n", "none", "remove all logs");
146 for(item = cpu_log_items; item->mask != 0; item++) {
147 term_printf("%-10s %s\n", item->name, item->help);
148 }
149 }
150 }
151 }
153 static void do_help(const char *name)
154 {
155 help_cmd(name);
156 }
158 static void do_commit(void)
159 {
160 int i;
162 for (i = 0; i < MAX_DISKS; i++) {
163 if (bs_table[i]) {
164 bdrv_commit(bs_table[i]);
165 }
166 }
167 }
169 static void do_info(const char *item)
170 {
171 term_cmd_t *cmd;
173 if (!item)
174 goto help;
175 for(cmd = info_cmds; cmd->name != NULL; cmd++) {
176 if (compare_cmd(item, cmd->name))
177 goto found;
178 }
179 help:
180 help_cmd("info");
181 return;
182 found:
183 cmd->handler();
184 }
186 static void do_info_version(void)
187 {
188 term_printf("%s\n", QEMU_VERSION);
189 }
191 static void do_info_network(void)
192 {
193 int i, j;
194 NetDriverState *nd;
196 for(i = 0; i < nb_nics; i++) {
197 nd = &nd_table[i];
198 term_printf("%d: ifname=%s macaddr=", i, nd->ifname);
199 for(j = 0; j < 6; j++) {
200 if (j > 0)
201 term_printf(":");
202 term_printf("%02x", nd->macaddr[j]);
203 }
204 term_printf("\n");
205 }
206 }
208 static void do_info_block(void)
209 {
210 bdrv_info();
211 }
213 static void do_info_history (void)
214 {
215 int i;
216 const char *str;
218 i = 0;
219 for(;;) {
220 str = readline_get_history(i);
221 if (!str)
222 break;
223 term_printf("%d: '%s'\n", i, str);
224 i++;
225 }
226 }
228 extern void destroy_vmx_domain(void);
229 static void do_quit(void)
230 {
231 destroy_vmx_domain();
232 exit(0);
233 }
235 static int eject_device(BlockDriverState *bs, int force)
236 {
237 if (bdrv_is_inserted(bs)) {
238 if (!force) {
239 if (!bdrv_is_removable(bs)) {
240 term_printf("device is not removable\n");
241 return -1;
242 }
243 if (bdrv_is_locked(bs)) {
244 term_printf("device is locked\n");
245 return -1;
246 }
247 }
248 bdrv_close(bs);
249 }
250 return 0;
251 }
253 static void do_eject(int force, const char *filename)
254 {
255 BlockDriverState *bs;
257 bs = bdrv_find(filename);
258 if (!bs) {
259 term_printf("device not found\n");
260 return;
261 }
262 eject_device(bs, force);
263 }
265 static void do_change(const char *device, const char *filename)
266 {
267 BlockDriverState *bs;
268 #if 0
269 int i;
270 char password[256];
271 #endif
273 bs = bdrv_find(device);
274 if (!bs) {
275 term_printf("device not found\n");
276 return;
277 }
278 if (eject_device(bs, 0) < 0)
279 return;
280 bdrv_open(bs, filename, 0);
281 #if 0
282 if (bdrv_is_encrypted(bs)) {
283 term_printf("%s is encrypted.\n", device);
284 for(i = 0; i < 3; i++) {
285 monitor_readline("Password: ", 1, password, sizeof(password));
286 if (bdrv_set_key(bs, password) == 0)
287 break;
288 term_printf("invalid password\n");
289 }
290 }
291 #endif
292 }
294 static void do_screen_dump(const char *filename)
295 {
296 vga_screen_dump(filename);
297 }
299 static void do_log(const char *items)
300 {
301 int mask;
303 if (!strcmp(items, "none")) {
304 mask = 0;
305 } else {
306 mask = cpu_str_to_log_mask(items);
307 if (!mask) {
308 help_cmd("log");
309 return;
310 }
311 }
312 cpu_set_log(mask);
313 }
315 static term_cmd_t term_cmds[] = {
316 { "help|?", "s?", do_help,
317 "[cmd]", "show the help" },
318 { "commit", "", do_commit,
319 "", "commit changes to the disk images (if -snapshot is used)" },
320 { "info", "s?", do_info,
321 "subcommand", "show various information about the system state" },
322 { "q|quit", "", do_quit,
323 "", "quit the emulator" },
324 { "eject", "-fB", do_eject,
325 "[-f] device", "eject a removable media (use -f to force it)" },
326 { "change", "BF", do_change,
327 "device filename", "change a removable media" },
328 { "screendump", "F", do_screen_dump,
329 "filename", "save screen into PPM image 'filename'" },
330 { "log", "s", do_log,
331 "item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
332 { "q|quit", "", do_quit,
333 "", "quit the emulator" },
334 { NULL, NULL, },
335 };
337 static term_cmd_t info_cmds[] = {
338 { "version", "", do_info_version,
339 "", "show the version of qemu" },
340 { "network", "", do_info_network,
341 "", "show the network state" },
342 { "block", "", do_info_block,
343 "", "show the block devices" },
344 { "history", "", do_info_history,
345 "", "show the command line history", },
346 { "irq", "", irq_info,
347 "", "show the interrupts statistics (if available)", },
348 { "pic", "", pic_info,
349 "", "show i8259 (PIC) state", },
350 { "pci", "", pci_info,
351 "", "show PCI info", },
352 { "vmxiopage", "", sp_info,
353 "", "show VMX device model shared page info", },
354 { NULL, NULL, },
355 };
357 static int get_str(char *buf, int buf_size, const char **pp)
358 {
359 const char *p;
360 char *q;
361 int c;
363 q = buf;
364 p = *pp;
365 while (isspace(*p))
366 p++;
367 if (*p == '\0') {
368 fail:
369 *q = '\0';
370 *pp = p;
371 return -1;
372 }
373 if (*p == '\"') {
374 p++;
375 while (*p != '\0' && *p != '\"') {
376 if (*p == '\\') {
377 p++;
378 c = *p++;
379 switch(c) {
380 case 'n':
381 c = '\n';
382 break;
383 case 'r':
384 c = '\r';
385 break;
386 case '\\':
387 case '\'':
388 case '\"':
389 break;
390 default:
391 qemu_printf("unsupported escape code: '\\%c'\n", c);
392 goto fail;
393 }
394 if ((q - buf) < buf_size - 1) {
395 *q++ = c;
396 }
397 } else {
398 if ((q - buf) < buf_size - 1) {
399 *q++ = *p;
400 }
401 p++;
402 }
403 }
404 if (*p != '\"') {
405 qemu_printf("unterminated string\n");
406 goto fail;
407 }
408 p++;
409 } else {
410 while (*p != '\0' && !isspace(*p)) {
411 if ((q - buf) < buf_size - 1) {
412 *q++ = *p;
413 }
414 p++;
415 }
416 }
417 *q = '\0';
418 *pp = p;
419 return 0;
420 }
422 #define MAX_ARGS 16
424 static void monitor_handle_command(const char *cmdline)
425 {
426 const char *p, *pstart, *typestr;
427 char *q;
428 int c, nb_args, len, i;
429 term_cmd_t *cmd;
430 char cmdname[256];
431 char buf[1024];
432 void *str_allocated[MAX_ARGS];
433 void *args[MAX_ARGS];
435 #ifdef DEBUG
436 term_printf("command='%s'\n", cmdline);
437 #endif
439 /* extract the command name */
440 p = cmdline;
441 q = cmdname;
442 while (isspace(*p))
443 p++;
444 if (*p == '\0')
445 return;
446 pstart = p;
447 while (*p != '\0' && *p != '/' && !isspace(*p))
448 p++;
449 len = p - pstart;
450 if (len > sizeof(cmdname) - 1)
451 len = sizeof(cmdname) - 1;
452 memcpy(cmdname, pstart, len);
453 cmdname[len] = '\0';
455 /* find the command */
456 for(cmd = term_cmds; cmd->name != NULL; cmd++) {
457 if (compare_cmd(cmdname, cmd->name))
458 goto found;
459 }
460 term_printf("unknown command: '%s'\n", cmdname);
461 return;
462 found:
464 for(i = 0; i < MAX_ARGS; i++)
465 str_allocated[i] = NULL;
467 /* parse the parameters */
468 typestr = cmd->args_type;
469 nb_args = 0;
470 for(;;) {
471 c = *typestr;
472 if (c == '\0')
473 break;
474 typestr++;
475 switch(c) {
476 case 'F':
477 case 'B':
478 case 's':
479 {
480 int ret;
481 char *str;
483 while (isspace(*p))
484 p++;
485 if (*typestr == '?') {
486 typestr++;
487 if (*p == '\0') {
488 /* no optional string: NULL argument */
489 str = NULL;
490 goto add_str;
491 }
492 }
493 ret = get_str(buf, sizeof(buf), &p);
494 if (ret < 0) {
495 switch(c) {
496 case 'F':
497 term_printf("%s: filename expected\n", cmdname);
498 break;
499 case 'B':
500 term_printf("%s: block device name expected\n", cmdname);
501 break;
502 default:
503 term_printf("%s: string expected\n", cmdname);
504 break;
505 }
506 goto fail;
507 }
508 str = qemu_malloc(strlen(buf) + 1);
509 strcpy(str, buf);
510 str_allocated[nb_args] = str;
511 add_str:
512 if (nb_args >= MAX_ARGS) {
513 error_args:
514 term_printf("%s: too many arguments\n", cmdname);
515 goto fail;
516 }
517 args[nb_args++] = str;
518 }
519 break;
520 case '-':
521 {
522 int has_option;
523 /* option */
525 c = *typestr++;
526 if (c == '\0')
527 goto bad_type;
528 while (isspace(*p))
529 p++;
530 has_option = 0;
531 if (*p == '-') {
532 p++;
533 if (*p != c) {
534 term_printf("%s: unsupported option -%c\n",
535 cmdname, *p);
536 goto fail;
537 }
538 p++;
539 has_option = 1;
540 }
541 if (nb_args >= MAX_ARGS)
542 goto error_args;
543 args[nb_args++] = (void *)has_option;
544 }
545 break;
546 /* TODO: add more commands we need here to support vmx device model */
547 case '/':
548 case 'i':
549 default:
550 bad_type:
551 term_printf("%s: unknown type '%c',not support now.\n", cmdname, c);
552 goto fail;
553 }
554 }
555 /* check that all arguments were parsed */
556 while (isspace(*p))
557 p++;
558 if (*p != '\0') {
559 term_printf("%s: extraneous characters at the end of line\n",
560 cmdname);
561 goto fail;
562 }
564 switch(nb_args) {
565 case 0:
566 cmd->handler();
567 break;
568 case 1:
569 cmd->handler(args[0]);
570 break;
571 case 2:
572 cmd->handler(args[0], args[1]);
573 break;
574 case 3:
575 cmd->handler(args[0], args[1], args[2]);
576 break;
577 case 4:
578 cmd->handler(args[0], args[1], args[2], args[3]);
579 break;
580 case 5:
581 cmd->handler(args[0], args[1], args[2], args[3], args[4]);
582 break;
583 case 6:
584 cmd->handler(args[0], args[1], args[2], args[3], args[4], args[5]);
585 break;
586 default:
587 term_printf("unsupported number of arguments: %d\n", nb_args);
588 goto fail;
589 }
590 fail:
591 for(i = 0; i < MAX_ARGS; i++)
592 qemu_free(str_allocated[i]);
593 return;
594 }
596 static int term_can_read(void *opaque)
597 {
598 return 128;
599 }
601 static void term_read(void *opaque, const uint8_t *buf, int size)
602 {
603 int i;
604 for(i = 0; i < size; i++)
605 readline_handle_byte(buf[i]);
606 }
608 static void monitor_start_input(void);
610 static void monitor_handle_command1(void *opaque, const char *cmdline)
611 {
612 monitor_handle_command(cmdline);
613 monitor_start_input();
614 }
616 static void monitor_start_input(void)
617 {
618 readline_start("(VTXen) ", 0, monitor_handle_command1, NULL);
619 }
621 void monitor_init(CharDriverState *hd, int show_banner)
622 {
623 monitor_hd = hd;
624 if (show_banner) {
625 term_printf("VMX device model. type 'q' to exit\n");
626 }
627 qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
628 monitor_start_input();
629 }