]>
git.proxmox.com Git - mirror_qemu.git/blob - monitor.c
4 * Copyright (c) 2003-2004 Fabrice Bellard
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
47 #define TERM_CMD_BUF_SIZE 4095
54 #define printf do_not_use_printf
56 static char term_cmd_buf
[TERM_CMD_BUF_SIZE
+ 1];
57 static int term_cmd_buf_index
;
58 static int term_cmd_buf_size
;
59 static int term_esc_state
;
60 static int term_esc_param
;
62 typedef struct term_cmd_t
{
64 void (*handler
)(int argc
, const char **argv
);
69 static term_cmd_t term_cmds
[];
70 static term_cmd_t info_cmds
[];
72 void term_printf(const char *fmt
, ...)
85 static int compare_cmd(const char *name
, const char *list
)
87 const char *p
, *pstart
;
95 p
= pstart
+ strlen(pstart
);
96 if ((p
- pstart
) == len
&& !memcmp(pstart
, name
, len
))
105 static void help_cmd1(term_cmd_t
*cmds
, const char *prefix
, const char *name
)
109 for(cmd
= cmds
; cmd
->name
!= NULL
; cmd
++) {
110 if (!name
|| !strcmp(name
, cmd
->name
))
111 term_printf("%s%s %s -- %s\n", prefix
, cmd
->name
, cmd
->params
, cmd
->help
);
115 static void help_cmd(const char *name
)
117 if (name
&& !strcmp(name
, "info")) {
118 help_cmd1(info_cmds
, "info ", NULL
);
120 help_cmd1(term_cmds
, "", name
);
124 static void do_help(int argc
, const char **argv
)
129 static void do_commit(int argc
, const char **argv
)
133 for (i
= 0; i
< MAX_DISKS
; i
++) {
135 bdrv_commit(bs_table
[i
]);
139 static void do_info(int argc
, const char **argv
)
147 for(cmd
= info_cmds
; cmd
->name
!= NULL
; cmd
++) {
148 if (compare_cmd(argv
[1], cmd
->name
))
155 cmd
->handler(argc
, argv
);
158 static void do_info_network(int argc
, const char **argv
)
163 for(i
= 0; i
< nb_nics
; i
++) {
165 term_printf("%d: ifname=%s macaddr=", i
, nd
->ifname
);
166 for(j
= 0; j
< 6; j
++) {
169 term_printf("%02x", nd
->macaddr
[j
]);
175 static void do_info_block(int argc
, const char **argv
)
180 static void do_quit(int argc
, const char **argv
)
185 static int eject_device(BlockDriverState
*bs
, int force
)
187 if (bdrv_is_inserted(bs
)) {
189 if (!bdrv_is_removable(bs
)) {
190 term_printf("device is not removable\n");
193 if (bdrv_is_locked(bs
)) {
194 term_printf("device is locked\n");
203 static void do_eject(int argc
, const char **argv
)
205 BlockDriverState
*bs
;
216 if (!strcmp(*parg
, "-f")) {
222 bs
= bdrv_find(*parg
);
224 term_printf("device not found\n");
227 eject_device(bs
, force
);
230 static void do_change(int argc
, const char **argv
)
232 BlockDriverState
*bs
;
238 bs
= bdrv_find(argv
[1]);
240 term_printf("device not found\n");
243 if (eject_device(bs
, 0) < 0)
245 bdrv_open(bs
, argv
[2], 0);
248 static term_cmd_t term_cmds
[] = {
250 "[cmd]", "show the help" },
251 { "commit", do_commit
,
252 "", "commit changes to the disk images (if -snapshot is used)" },
254 "subcommand", "show various information about the system state" },
256 "", "quit the emulator" },
258 "[-f] device", "eject a removable media (use -f to force it)" },
259 { "change", do_change
,
260 "device filename", "change a removable media" },
264 static term_cmd_t info_cmds
[] = {
265 { "network", do_info_network
,
266 "", "show the network state" },
267 { "block", do_info_block
,
268 "", "show the block devices" },
272 static void term_handle_command(char *cmdline
)
276 const char *args
[MAX_ARGS
+ 1];
280 term_printf("command='%s'\n", cmdline
);
283 /* split command in words */
292 while (*p
!= '\0' && !isspace(*p
))
296 if (argc
>= MAX_ARGS
)
304 for(i
=0;i
<argc
;i
++) {
305 term_printf(" '%s'", args
[i
]);
311 for(cmd
= term_cmds
; cmd
->name
!= NULL
; cmd
++) {
312 if (compare_cmd(args
[0], cmd
->name
))
315 term_printf("unknown command: '%s'\n", args
[0]);
318 cmd
->handler(argc
, args
);
321 static void term_show_prompt(void)
323 term_printf("(qemu) ");
325 term_cmd_buf_index
= 0;
326 term_cmd_buf_size
= 0;
327 term_esc_state
= IS_NORM
;
330 static void term_insert_char(int ch
)
332 if (term_cmd_buf_index
< TERM_CMD_BUF_SIZE
) {
333 memmove(term_cmd_buf
+ term_cmd_buf_index
+ 1,
334 term_cmd_buf
+ term_cmd_buf_index
,
335 term_cmd_buf_size
- term_cmd_buf_index
);
336 term_cmd_buf
[term_cmd_buf_index
] = ch
;
338 term_printf("\033[@%c", ch
);
339 term_cmd_buf_index
++;
344 static void term_backward_char(void)
346 if (term_cmd_buf_index
> 0) {
347 term_cmd_buf_index
--;
348 term_printf("\033[D");
353 static void term_forward_char(void)
355 if (term_cmd_buf_index
< term_cmd_buf_size
) {
356 term_cmd_buf_index
++;
357 term_printf("\033[C");
362 static void term_delete_char(void)
364 if (term_cmd_buf_index
< term_cmd_buf_size
) {
365 memmove(term_cmd_buf
+ term_cmd_buf_index
,
366 term_cmd_buf
+ term_cmd_buf_index
+ 1,
367 term_cmd_buf_size
- term_cmd_buf_index
- 1);
368 term_printf("\033[P");
374 static void term_backspace(void)
376 if (term_cmd_buf_index
> 0) {
377 term_backward_char();
382 static void term_bol(void)
384 while (term_cmd_buf_index
> 0)
385 term_backward_char();
388 static void term_eol(void)
390 while (term_cmd_buf_index
< term_cmd_buf_size
)
394 /* return true if command handled */
395 static void term_handle_byte(int ch
)
397 switch(term_esc_state
) {
408 term_cmd_buf
[term_cmd_buf_size
] = '\0';
410 term_handle_command(term_cmd_buf
);
414 term_esc_state
= IS_ESC
;
422 term_insert_char(ch
);
429 term_esc_state
= IS_CSI
;
432 term_esc_state
= IS_NORM
;
438 term_backward_char();
444 term_esc_param
= term_esc_param
* 10 + (ch
- '0');
447 switch(term_esc_param
) {
462 term_esc_state
= IS_NORM
;
468 /*************************************************************/
469 /* serial console support */
471 #define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
473 static int term_got_escape
, term_command
;
475 void term_print_help(void)
478 "C-a h print this help\n"
479 "C-a x exit emulatior\n"
480 "C-a d switch on/off debug log\n"
481 "C-a s save disk data back to file (if -snapshot)\n"
482 "C-a b send break (magic sysrq)\n"
483 "C-a c switch between console and monitor\n"
488 /* called when a char is received */
489 static void term_received_byte(int ch
)
491 if (!serial_console
) {
492 /* if no serial console, handle every command */
493 term_handle_byte(ch
);
495 if (term_got_escape
) {
507 for (i
= 0; i
< MAX_DISKS
; i
++) {
509 bdrv_commit(bs_table
[i
]);
515 serial_receive_break(serial_console
);
526 cpu_set_log(CPU_LOG_ALL
);
531 } else if (ch
== TERM_ESCAPE
) {
536 term_handle_byte(ch
);
539 serial_receive_byte(serial_console
, ch
);
545 static int term_can_read(void *opaque
)
547 if (serial_console
) {
548 return serial_can_receive(serial_console
);
554 static void term_read(void *opaque
, const uint8_t *buf
, int size
)
557 for(i
= 0; i
< size
; i
++)
558 term_received_byte(buf
[i
]);
561 void monitor_init(void)
563 if (!serial_console
) {
564 term_printf("QEMU %s monitor - type 'help' for more information\n",
568 add_fd_read_handler(0, term_can_read
, term_read
, NULL
);