Commit 81d0912d2d221c41d649d2c36812afddf74634d2

Authored by bellard
1 parent d1d9f421

completion support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1020 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 348 additions and 113 deletions
... ... @@ -470,6 +470,15 @@ BlockDriverState *bdrv_find(const char *name)
470 470 return NULL;
471 471 }
472 472  
  473 +void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
  474 +{
  475 + BlockDriverState *bs;
  476 +
  477 + for (bs = bdrv_first; bs != NULL; bs = bs->next) {
  478 + it(opaque, bs->device_name);
  479 + }
  480 +}
  481 +
473 482 void bdrv_info(void)
474 483 {
475 484 BlockDriverState *bs;
... ...
monitor.c
... ... @@ -23,8 +23,10 @@
23 23 */
24 24 #include "vl.h"
25 25 #include "disas.h"
  26 +#include <dirent.h>
26 27  
27 28 //#define DEBUG
  29 +//#define DEBUG_COMPLETION
28 30  
29 31 #ifndef offsetof
30 32 #define offsetof(type, field) ((size_t) &((type *)0)->field)
... ... @@ -32,6 +34,7 @@
32 34  
33 35 #define TERM_CMD_BUF_SIZE 4095
34 36 #define TERM_MAX_CMDS 64
  37 +#define NB_COMPLETIONS_MAX 256
35 38  
36 39 #define IS_NORM 0
37 40 #define IS_ESC 1
... ... @@ -42,16 +45,28 @@
42 45 static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];
43 46 static int term_cmd_buf_index;
44 47 static int term_cmd_buf_size;
  48 +
  49 +static char term_last_cmd_buf[TERM_CMD_BUF_SIZE + 1];
  50 +static int term_last_cmd_buf_index;
  51 +static int term_last_cmd_buf_size;
  52 +
45 53 static int term_esc_state;
46 54 static int term_esc_param;
47 55  
48 56 static char *term_history[TERM_MAX_CMDS];
49 57 static int term_hist_entry;
  58 +static CharDriverState *monitor_hd;
  59 +
  60 +static int nb_completions;
  61 +static int completion_index;
  62 +static char *completions[NB_COMPLETIONS_MAX];
  63 +
50 64  
51 65 /*
52 66 * Supported types:
53 67 *
54 68 * 'F' filename
  69 + * 'B' block device name
55 70 * 's' string (accept optional quote)
56 71 * 'i' integer
57 72 * '/' optional gdb-like print format (like "/10x")
... ... @@ -71,17 +86,20 @@ typedef struct term_cmd_t {
71 86 static term_cmd_t term_cmds[];
72 87 static term_cmd_t info_cmds[];
73 88  
  89 +static void add_completion(const char *str);
  90 +
74 91 void term_printf(const char *fmt, ...)
75 92 {
  93 + char buf[4096];
76 94 va_list ap;
77 95 va_start(ap, fmt);
78   - vprintf(fmt, ap);
  96 + vsnprintf(buf, sizeof(buf), fmt, ap);
  97 + qemu_chr_write(monitor_hd, buf, strlen(buf));
79 98 va_end(ap);
80 99 }
81 100  
82 101 void term_flush(void)
83 102 {
84   - fflush(stdout);
85 103 }
86 104  
87 105 static int compare_cmd(const char *name, const char *list)
... ... @@ -232,8 +250,6 @@ static void do_eject(int force, const char *filename)
232 250 {
233 251 BlockDriverState *bs;
234 252  
235   - term_printf("%d %s\n", force, filename);
236   -
237 253 bs = bdrv_find(filename);
238 254 if (!bs) {
239 255 term_printf("device not found\n");
... ... @@ -674,9 +690,9 @@ static term_cmd_t term_cmds[] = {
674 690 "subcommand", "show various information about the system state" },
675 691 { "q|quit", "", do_quit,
676 692 "", "quit the emulator" },
677   - { "eject", "-fs", do_eject,
  693 + { "eject", "-fB", do_eject,
678 694 "[-f] device", "eject a removable media (use -f to force it)" },
679   - { "change", "sF", do_change,
  695 + { "change", "BF", do_change,
680 696 "device filename", "change a removable media" },
681 697 { "screendump", "F", do_screen_dump,
682 698 "filename", "save screen into PPM image 'filename'" },
... ... @@ -953,6 +969,16 @@ static int expr_unary(void)
953 969 }
954 970 next();
955 971 break;
  972 + case '\'':
  973 + pch++;
  974 + if (*pch == '\0')
  975 + expr_error("character constant expected");
  976 + n = *pch;
  977 + pch++;
  978 + if (*pch != '\'')
  979 + expr_error("missing terminating \' character");
  980 + next();
  981 + break;
956 982 case '$':
957 983 {
958 984 char buf[128], *q;
... ... @@ -1088,15 +1114,16 @@ static int get_str(char *buf, int buf_size, const char **pp)
1088 1114 char *q;
1089 1115 int c;
1090 1116  
  1117 + q = buf;
1091 1118 p = *pp;
1092 1119 while (isspace(*p))
1093 1120 p++;
1094 1121 if (*p == '\0') {
1095 1122 fail:
  1123 + *q = '\0';
1096 1124 *pp = p;
1097 1125 return -1;
1098 1126 }
1099   - q = buf;
1100 1127 if (*p == '\"') {
1101 1128 p++;
1102 1129 while (*p != '\0' && *p != '\"') {
... ... @@ -1140,8 +1167,8 @@ static int get_str(char *buf, int buf_size, const char **pp)
1140 1167 }
1141 1168 p++;
1142 1169 }
1143   - *q = '\0';
1144 1170 }
  1171 + *q = '\0';
1145 1172 *pp = p;
1146 1173 return 0;
1147 1174 }
... ... @@ -1204,6 +1231,7 @@ static void term_handle_command(const char *cmdline)
1204 1231 typestr++;
1205 1232 switch(c) {
1206 1233 case 'F':
  1234 + case 'B':
1207 1235 case 's':
1208 1236 {
1209 1237 int ret;
... ... @@ -1221,10 +1249,17 @@ static void term_handle_command(const char *cmdline)
1221 1249 }
1222 1250 ret = get_str(buf, sizeof(buf), &p);
1223 1251 if (ret < 0) {
1224   - if (c == 'F')
  1252 + switch(c) {
  1253 + case 'F':
1225 1254 term_printf("%s: filename expected\n", cmdname);
1226   - else
  1255 + break;
  1256 + case 'B':
  1257 + term_printf("%s: block device name expected\n", cmdname);
  1258 + break;
  1259 + default:
1227 1260 term_printf("%s: string expected\n", cmdname);
  1261 + break;
  1262 + }
1228 1263 goto fail;
1229 1264 }
1230 1265 str = qemu_malloc(strlen(buf) + 1);
... ... @@ -1432,19 +1467,232 @@ static void term_handle_command(const char *cmdline)
1432 1467 return;
1433 1468 }
1434 1469  
1435   -static void term_show_prompt(void)
  1470 +static void cmd_completion(const char *name, const char *list)
  1471 +{
  1472 + const char *p, *pstart;
  1473 + char cmd[128];
  1474 + int len;
  1475 +
  1476 + p = list;
  1477 + for(;;) {
  1478 + pstart = p;
  1479 + p = strchr(p, '|');
  1480 + if (!p)
  1481 + p = pstart + strlen(pstart);
  1482 + len = p - pstart;
  1483 + if (len > sizeof(cmd) - 2)
  1484 + len = sizeof(cmd) - 2;
  1485 + memcpy(cmd, pstart, len);
  1486 + cmd[len] = '\0';
  1487 + if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
  1488 + add_completion(cmd);
  1489 + }
  1490 + if (*p == '\0')
  1491 + break;
  1492 + p++;
  1493 + }
  1494 +}
  1495 +
  1496 +static void file_completion(const char *input)
  1497 +{
  1498 + DIR *ffs;
  1499 + struct dirent *d;
  1500 + char path[1024];
  1501 + char file[1024], file_prefix[1024];
  1502 + int input_path_len;
  1503 + const char *p;
  1504 +
  1505 + p = strrchr(input, '/');
  1506 + if (!p) {
  1507 + input_path_len = 0;
  1508 + pstrcpy(file_prefix, sizeof(file_prefix), input);
  1509 + strcpy(path, ".");
  1510 + } else {
  1511 + input_path_len = p - input + 1;
  1512 + memcpy(path, input, input_path_len);
  1513 + if (input_path_len > sizeof(path) - 1)
  1514 + input_path_len = sizeof(path) - 1;
  1515 + path[input_path_len] = '\0';
  1516 + pstrcpy(file_prefix, sizeof(file_prefix), p + 1);
  1517 + }
  1518 +#ifdef DEBUG_COMPLETION
  1519 + term_printf("input='%s' path='%s' prefix='%s'\n", input, path, file_prefix);
  1520 +#endif
  1521 + ffs = opendir(path);
  1522 + if (!ffs)
  1523 + return;
  1524 + for(;;) {
  1525 + struct stat sb;
  1526 + d = readdir(ffs);
  1527 + if (!d)
  1528 + break;
  1529 + if (strstart(d->d_name, file_prefix, NULL)) {
  1530 + memcpy(file, input, input_path_len);
  1531 + strcpy(file + input_path_len, d->d_name);
  1532 + /* stat the file to find out if it's a directory.
  1533 + * In that case add a slash to speed up typing long paths
  1534 + */
  1535 + stat(file, &sb);
  1536 + if(S_ISDIR(sb.st_mode))
  1537 + strcat(file, "/");
  1538 + add_completion(file);
  1539 + }
  1540 + }
  1541 + closedir(ffs);
  1542 +}
  1543 +
  1544 +static void block_completion_it(void *opaque, const char *name)
  1545 +{
  1546 + const char *input = opaque;
  1547 +
  1548 + if (input[0] == '\0' ||
  1549 + !strncmp(name, (char *)input, strlen(input))) {
  1550 + add_completion(name);
  1551 + }
  1552 +}
  1553 +
  1554 +/* NOTE: this parser is an approximate form of the real command parser */
  1555 +static void parse_cmdline(const char *cmdline,
  1556 + int *pnb_args, char **args)
  1557 +{
  1558 + const char *p;
  1559 + int nb_args, ret;
  1560 + char buf[1024];
  1561 +
  1562 + p = cmdline;
  1563 + nb_args = 0;
  1564 + for(;;) {
  1565 + while (isspace(*p))
  1566 + p++;
  1567 + if (*p == '\0')
  1568 + break;
  1569 + if (nb_args >= MAX_ARGS)
  1570 + break;
  1571 + ret = get_str(buf, sizeof(buf), &p);
  1572 + args[nb_args] = qemu_strdup(buf);
  1573 + nb_args++;
  1574 + if (ret < 0)
  1575 + break;
  1576 + }
  1577 + *pnb_args = nb_args;
  1578 +}
  1579 +
  1580 +static void find_completion(const char *cmdline)
  1581 +{
  1582 + const char *cmdname;
  1583 + char *args[MAX_ARGS];
  1584 + int nb_args, i, len;
  1585 + const char *ptype, *str;
  1586 + term_cmd_t *cmd;
  1587 +
  1588 + parse_cmdline(cmdline, &nb_args, args);
  1589 +#ifdef DEBUG_COMPLETION
  1590 + for(i = 0; i < nb_args; i++) {
  1591 + term_printf("arg%d = '%s'\n", i, (char *)args[i]);
  1592 + }
  1593 +#endif
  1594 +
  1595 + /* if the line ends with a space, it means we want to complete the
  1596 + next arg */
  1597 + len = strlen(cmdline);
  1598 + if (len > 0 && isspace(cmdline[len - 1])) {
  1599 + if (nb_args >= MAX_ARGS)
  1600 + return;
  1601 + args[nb_args++] = qemu_strdup("");
  1602 + }
  1603 + if (nb_args <= 1) {
  1604 + /* command completion */
  1605 + if (nb_args == 0)
  1606 + cmdname = "";
  1607 + else
  1608 + cmdname = args[0];
  1609 + completion_index = strlen(cmdname);
  1610 + for(cmd = term_cmds; cmd->name != NULL; cmd++) {
  1611 + cmd_completion(cmdname, cmd->name);
  1612 + }
  1613 + } else {
  1614 + /* find the command */
  1615 + for(cmd = term_cmds; cmd->name != NULL; cmd++) {
  1616 + if (compare_cmd(args[0], cmd->name))
  1617 + goto found;
  1618 + }
  1619 + return;
  1620 + found:
  1621 + ptype = cmd->args_type;
  1622 + for(i = 0; i < nb_args - 2; i++) {
  1623 + if (*ptype != '\0') {
  1624 + ptype++;
  1625 + while (*ptype == '?')
  1626 + ptype++;
  1627 + }
  1628 + }
  1629 + str = args[nb_args - 1];
  1630 + switch(*ptype) {
  1631 + case 'F':
  1632 + /* file completion */
  1633 + completion_index = strlen(str);
  1634 + file_completion(str);
  1635 + break;
  1636 + case 'B':
  1637 + /* block device name completion */
  1638 + completion_index = strlen(str);
  1639 + bdrv_iterate(block_completion_it, (void *)str);
  1640 + break;
  1641 + default:
  1642 + break;
  1643 + }
  1644 + }
  1645 + for(i = 0; i < nb_args; i++)
  1646 + qemu_free(args[i]);
  1647 +}
  1648 +
  1649 +static void term_show_prompt2(void)
1436 1650 {
1437 1651 term_printf("(qemu) ");
1438 1652 fflush(stdout);
  1653 + term_last_cmd_buf_index = 0;
  1654 + term_last_cmd_buf_size = 0;
  1655 + term_esc_state = IS_NORM;
  1656 +}
  1657 +
  1658 +static void term_show_prompt(void)
  1659 +{
  1660 + term_show_prompt2();
1439 1661 term_cmd_buf_index = 0;
1440 1662 term_cmd_buf_size = 0;
1441   - term_esc_state = IS_NORM;
1442 1663 }
1443 1664  
1444   -static void term_print_cmdline (const char *cmdline)
  1665 +/* update the displayed command line */
  1666 +static void term_update(void)
1445 1667 {
1446   - term_show_prompt();
1447   - term_printf("%s", cmdline);
  1668 + int i, delta;
  1669 +
  1670 + if (term_cmd_buf_size != term_last_cmd_buf_size ||
  1671 + memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) {
  1672 + for(i = 0; i < term_last_cmd_buf_index; i++) {
  1673 + term_printf("\033[D");
  1674 + }
  1675 + term_cmd_buf[term_cmd_buf_size] = '\0';
  1676 + term_printf("%s", term_cmd_buf);
  1677 + term_printf("\033[K");
  1678 + memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size);
  1679 + term_last_cmd_buf_size = term_cmd_buf_size;
  1680 + term_last_cmd_buf_index = term_cmd_buf_size;
  1681 + }
  1682 + if (term_cmd_buf_index != term_last_cmd_buf_index) {
  1683 + delta = term_cmd_buf_index - term_last_cmd_buf_index;
  1684 + if (delta > 0) {
  1685 + for(i = 0;i < delta; i++) {
  1686 + term_printf("\033[C");
  1687 + }
  1688 + } else {
  1689 + delta = -delta;
  1690 + for(i = 0;i < delta; i++) {
  1691 + term_printf("\033[D");
  1692 + }
  1693 + }
  1694 + term_last_cmd_buf_index = term_cmd_buf_index;
  1695 + }
1448 1696 term_flush();
1449 1697 }
1450 1698  
... ... @@ -1456,9 +1704,7 @@ static void term_insert_char(int ch)
1456 1704 term_cmd_buf_size - term_cmd_buf_index);
1457 1705 term_cmd_buf[term_cmd_buf_index] = ch;
1458 1706 term_cmd_buf_size++;
1459   - term_printf("\033[@%c", ch);
1460 1707 term_cmd_buf_index++;
1461   - term_flush();
1462 1708 }
1463 1709 }
1464 1710  
... ... @@ -1466,8 +1712,6 @@ static void term_backward_char(void)
1466 1712 {
1467 1713 if (term_cmd_buf_index > 0) {
1468 1714 term_cmd_buf_index--;
1469   - term_printf("\033[D");
1470   - term_flush();
1471 1715 }
1472 1716 }
1473 1717  
... ... @@ -1475,8 +1719,6 @@ static void term_forward_char(void)
1475 1719 {
1476 1720 if (term_cmd_buf_index < term_cmd_buf_size) {
1477 1721 term_cmd_buf_index++;
1478   - term_printf("\033[C");
1479   - term_flush();
1480 1722 }
1481 1723 }
1482 1724  
... ... @@ -1486,9 +1728,7 @@ static void term_delete_char(void)
1486 1728 memmove(term_cmd_buf + term_cmd_buf_index,
1487 1729 term_cmd_buf + term_cmd_buf_index + 1,
1488 1730 term_cmd_buf_size - term_cmd_buf_index - 1);
1489   - term_printf("\033[P");
1490 1731 term_cmd_buf_size--;
1491   - term_flush();
1492 1732 }
1493 1733 }
1494 1734  
... ... @@ -1502,14 +1742,12 @@ static void term_backspace(void)
1502 1742  
1503 1743 static void term_bol(void)
1504 1744 {
1505   - while (term_cmd_buf_index > 0)
1506   - term_backward_char();
  1745 + term_cmd_buf_index = 0;
1507 1746 }
1508 1747  
1509 1748 static void term_eol(void)
1510 1749 {
1511   - while (term_cmd_buf_index < term_cmd_buf_size)
1512   - term_forward_char();
  1750 + term_cmd_buf_index = term_cmd_buf_size;
1513 1751 }
1514 1752  
1515 1753 static void term_up_char(void)
... ... @@ -1530,8 +1768,6 @@ static void term_up_char(void)
1530 1768 if (term_hist_entry >= 0) {
1531 1769 pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
1532 1770 term_history[term_hist_entry]);
1533   - term_printf("\n");
1534   - term_print_cmdline(term_cmd_buf);
1535 1771 term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
1536 1772 }
1537 1773 }
... ... @@ -1546,8 +1782,6 @@ static void term_down_char(void)
1546 1782 } else {
1547 1783 term_hist_entry = -1;
1548 1784 }
1549   - term_printf("\n");
1550   - term_print_cmdline(term_cmd_buf);
1551 1785 term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
1552 1786 }
1553 1787  
... ... @@ -1600,6 +1834,67 @@ static void term_hist_add(const char *cmdline)
1600 1834 term_hist_entry = -1;
1601 1835 }
1602 1836  
  1837 +/* completion support */
  1838 +
  1839 +static void add_completion(const char *str)
  1840 +{
  1841 + if (nb_completions < NB_COMPLETIONS_MAX) {
  1842 + completions[nb_completions++] = qemu_strdup(str);
  1843 + }
  1844 +}
  1845 +
  1846 +static void term_completion(void)
  1847 +{
  1848 + int len, i, j, max_width, nb_cols;
  1849 + char *cmdline;
  1850 +
  1851 + nb_completions = 0;
  1852 +
  1853 + cmdline = qemu_malloc(term_cmd_buf_index + 1);
  1854 + if (!cmdline)
  1855 + return;
  1856 + memcpy(cmdline, term_cmd_buf, term_cmd_buf_index);
  1857 + cmdline[term_cmd_buf_index] = '\0';
  1858 + find_completion(cmdline);
  1859 + qemu_free(cmdline);
  1860 +
  1861 + /* no completion found */
  1862 + if (nb_completions <= 0)
  1863 + return;
  1864 + if (nb_completions == 1) {
  1865 + len = strlen(completions[0]);
  1866 + for(i = completion_index; i < len; i++) {
  1867 + term_insert_char(completions[0][i]);
  1868 + }
  1869 + /* extra space for next argument. XXX: make it more generic */
  1870 + if (len > 0 && completions[0][len - 1] != '/')
  1871 + term_insert_char(' ');
  1872 + } else {
  1873 + term_printf("\n");
  1874 + max_width = 0;
  1875 + for(i = 0; i < nb_completions; i++) {
  1876 + len = strlen(completions[i]);
  1877 + if (len > max_width)
  1878 + max_width = len;
  1879 + }
  1880 + max_width += 2;
  1881 + if (max_width < 10)
  1882 + max_width = 10;
  1883 + else if (max_width > 80)
  1884 + max_width = 80;
  1885 + nb_cols = 80 / max_width;
  1886 + j = 0;
  1887 + for(i = 0; i < nb_completions; i++) {
  1888 + term_printf("%-*s", max_width, completions[i]);
  1889 + if (++j == nb_cols || i == (nb_completions - 1)) {
  1890 + term_printf("\n");
  1891 + j = 0;
  1892 + }
  1893 + }
  1894 + term_show_prompt2();
  1895 + }
  1896 +}
  1897 +
1603 1898 /* return true if command handled */
1604 1899 static void term_handle_byte(int ch)
1605 1900 {
... ... @@ -1609,9 +1904,15 @@ static void term_handle_byte(int ch)
1609 1904 case 1:
1610 1905 term_bol();
1611 1906 break;
  1907 + case 4:
  1908 + term_delete_char();
  1909 + break;
1612 1910 case 5:
1613 1911 term_eol();
1614 1912 break;
  1913 + case 9:
  1914 + term_completion();
  1915 + break;
1615 1916 case 10:
1616 1917 case 13:
1617 1918 term_cmd_buf[term_cmd_buf_size] = '\0';
... ... @@ -1684,104 +1985,29 @@ static void term_handle_byte(int ch)
1684 1985 the_end:
1685 1986 break;
1686 1987 }
1687   -}
1688   -
1689   -/*************************************************************/
1690   -/* serial console support */
1691   -
1692   -#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
1693   -
1694   -static int term_got_escape, term_command;
1695   -
1696   -void term_print_help(void)
1697   -{
1698   - term_printf("\n"
1699   - "C-a h print this help\n"
1700   - "C-a x exit emulatior\n"
1701   - "C-a s save disk data back to file (if -snapshot)\n"
1702   - "C-a b send break (magic sysrq)\n"
1703   - "C-a c switch between console and monitor\n"
1704   - "C-a C-a send C-a\n"
1705   - );
1706   -}
1707   -
1708   -/* called when a char is received */
1709   -static void term_received_byte(int ch)
1710   -{
1711   - if (!serial_console) {
1712   - /* if no serial console, handle every command */
1713   - term_handle_byte(ch);
1714   - } else {
1715   - if (term_got_escape) {
1716   - term_got_escape = 0;
1717   - switch(ch) {
1718   - case 'h':
1719   - term_print_help();
1720   - break;
1721   - case 'x':
1722   - exit(0);
1723   - break;
1724   - case 's':
1725   - {
1726   - int i;
1727   - for (i = 0; i < MAX_DISKS; i++) {
1728   - if (bs_table[i])
1729   - bdrv_commit(bs_table[i]);
1730   - }
1731   - }
1732   - break;
1733   - case 'b':
1734   - if (serial_console)
1735   - serial_receive_break(serial_console);
1736   - break;
1737   - case 'c':
1738   - if (!term_command) {
1739   - term_show_prompt();
1740   - term_command = 1;
1741   - } else {
1742   - term_command = 0;
1743   - }
1744   - break;
1745   - case TERM_ESCAPE:
1746   - goto send_char;
1747   - }
1748   - } else if (ch == TERM_ESCAPE) {
1749   - term_got_escape = 1;
1750   - } else {
1751   - send_char:
1752   - if (term_command) {
1753   - term_handle_byte(ch);
1754   - } else {
1755   - if (serial_console)
1756   - serial_receive_byte(serial_console, ch);
1757   - }
1758   - }
1759   - }
  1988 + term_update();
1760 1989 }
1761 1990  
1762 1991 static int term_can_read(void *opaque)
1763 1992 {
1764   - if (serial_console) {
1765   - return serial_can_receive(serial_console);
1766   - } else {
1767   - return 128;
1768   - }
  1993 + return 128;
1769 1994 }
1770 1995  
1771 1996 static void term_read(void *opaque, const uint8_t *buf, int size)
1772 1997 {
1773 1998 int i;
1774 1999 for(i = 0; i < size; i++)
1775   - term_received_byte(buf[i]);
  2000 + term_handle_byte(buf[i]);
1776 2001 }
1777 2002  
1778   -void monitor_init(void)
  2003 +void monitor_init(CharDriverState *hd, int show_banner)
1779 2004 {
1780   - if (!serial_console) {
  2005 + monitor_hd = hd;
  2006 + if (show_banner) {
1781 2007 term_printf("QEMU %s monitor - type 'help' for more information\n",
1782 2008 QEMU_VERSION);
1783 2009 term_show_prompt();
1784 2010 }
1785 2011 term_hist_entry = -1;
1786   - qemu_add_fd_read_handler(0, term_can_read, term_read, NULL);
  2012 + qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
1787 2013 }
... ...