1ed7bda5dSKevin Wolf /* 2ed7bda5dSKevin Wolf * QEMU monitor 3ed7bda5dSKevin Wolf * 4ed7bda5dSKevin Wolf * Copyright (c) 2003-2004 Fabrice Bellard 5ed7bda5dSKevin Wolf * 6ed7bda5dSKevin Wolf * Permission is hereby granted, free of charge, to any person obtaining a copy 7ed7bda5dSKevin Wolf * of this software and associated documentation files (the "Software"), to deal 8ed7bda5dSKevin Wolf * in the Software without restriction, including without limitation the rights 9ed7bda5dSKevin Wolf * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10ed7bda5dSKevin Wolf * copies of the Software, and to permit persons to whom the Software is 11ed7bda5dSKevin Wolf * furnished to do so, subject to the following conditions: 12ed7bda5dSKevin Wolf * 13ed7bda5dSKevin Wolf * The above copyright notice and this permission notice shall be included in 14ed7bda5dSKevin Wolf * all copies or substantial portions of the Software. 15ed7bda5dSKevin Wolf * 16ed7bda5dSKevin Wolf * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17ed7bda5dSKevin Wolf * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18ed7bda5dSKevin Wolf * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19ed7bda5dSKevin Wolf * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20ed7bda5dSKevin Wolf * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21ed7bda5dSKevin Wolf * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22ed7bda5dSKevin Wolf * THE SOFTWARE. 23ed7bda5dSKevin Wolf */ 24ed7bda5dSKevin Wolf 25ed7bda5dSKevin Wolf #include "qemu/osdep.h" 26ed7bda5dSKevin Wolf #include <dirent.h> 27ed7bda5dSKevin Wolf #include "monitor-internal.h" 28ed7bda5dSKevin Wolf #include "qapi/error.h" 29ed7bda5dSKevin Wolf #include "qapi/qmp/qdict.h" 30ed7bda5dSKevin Wolf #include "qapi/qmp/qnum.h" 31ed7bda5dSKevin Wolf #include "qemu/config-file.h" 32ed7bda5dSKevin Wolf #include "qemu/ctype.h" 33ed7bda5dSKevin Wolf #include "qemu/cutils.h" 34ed7bda5dSKevin Wolf #include "qemu/log.h" 35ed7bda5dSKevin Wolf #include "qemu/option.h" 36ed7bda5dSKevin Wolf #include "qemu/units.h" 37ed7bda5dSKevin Wolf #include "sysemu/block-backend.h" 3854d31236SMarkus Armbruster #include "sysemu/runstate.h" 39ed7bda5dSKevin Wolf #include "trace.h" 40ed7bda5dSKevin Wolf 41ed7bda5dSKevin Wolf static void monitor_command_cb(void *opaque, const char *cmdline, 42ed7bda5dSKevin Wolf void *readline_opaque) 43ed7bda5dSKevin Wolf { 44ed7bda5dSKevin Wolf MonitorHMP *mon = opaque; 45ed7bda5dSKevin Wolf 46ed7bda5dSKevin Wolf monitor_suspend(&mon->common); 47ed7bda5dSKevin Wolf handle_hmp_command(mon, cmdline); 48ed7bda5dSKevin Wolf monitor_resume(&mon->common); 49ed7bda5dSKevin Wolf } 50ed7bda5dSKevin Wolf 51ed7bda5dSKevin Wolf void monitor_read_command(MonitorHMP *mon, int show_prompt) 52ed7bda5dSKevin Wolf { 53ed7bda5dSKevin Wolf if (!mon->rs) { 54ed7bda5dSKevin Wolf return; 55ed7bda5dSKevin Wolf } 56ed7bda5dSKevin Wolf 57ed7bda5dSKevin Wolf readline_start(mon->rs, "(qemu) ", 0, monitor_command_cb, NULL); 58ed7bda5dSKevin Wolf if (show_prompt) { 59ed7bda5dSKevin Wolf readline_show_prompt(mon->rs); 60ed7bda5dSKevin Wolf } 61ed7bda5dSKevin Wolf } 62ed7bda5dSKevin Wolf 63ed7bda5dSKevin Wolf int monitor_read_password(MonitorHMP *mon, ReadLineFunc *readline_func, 64ed7bda5dSKevin Wolf void *opaque) 65ed7bda5dSKevin Wolf { 66ed7bda5dSKevin Wolf if (mon->rs) { 67ed7bda5dSKevin Wolf readline_start(mon->rs, "Password: ", 1, readline_func, opaque); 68ed7bda5dSKevin Wolf /* prompt is printed on return from the command handler */ 69ed7bda5dSKevin Wolf return 0; 70ed7bda5dSKevin Wolf } else { 71ed7bda5dSKevin Wolf monitor_printf(&mon->common, 72ed7bda5dSKevin Wolf "terminal does not support password prompting\n"); 73ed7bda5dSKevin Wolf return -ENOTTY; 74ed7bda5dSKevin Wolf } 75ed7bda5dSKevin Wolf } 76ed7bda5dSKevin Wolf 77ed7bda5dSKevin Wolf static int get_str(char *buf, int buf_size, const char **pp) 78ed7bda5dSKevin Wolf { 79ed7bda5dSKevin Wolf const char *p; 80ed7bda5dSKevin Wolf char *q; 81ed7bda5dSKevin Wolf int c; 82ed7bda5dSKevin Wolf 83ed7bda5dSKevin Wolf q = buf; 84ed7bda5dSKevin Wolf p = *pp; 85ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 86ed7bda5dSKevin Wolf p++; 87ed7bda5dSKevin Wolf } 88ed7bda5dSKevin Wolf if (*p == '\0') { 89ed7bda5dSKevin Wolf fail: 90ed7bda5dSKevin Wolf *q = '\0'; 91ed7bda5dSKevin Wolf *pp = p; 92ed7bda5dSKevin Wolf return -1; 93ed7bda5dSKevin Wolf } 94ed7bda5dSKevin Wolf if (*p == '\"') { 95ed7bda5dSKevin Wolf p++; 96ed7bda5dSKevin Wolf while (*p != '\0' && *p != '\"') { 97ed7bda5dSKevin Wolf if (*p == '\\') { 98ed7bda5dSKevin Wolf p++; 99ed7bda5dSKevin Wolf c = *p++; 100ed7bda5dSKevin Wolf switch (c) { 101ed7bda5dSKevin Wolf case 'n': 102ed7bda5dSKevin Wolf c = '\n'; 103ed7bda5dSKevin Wolf break; 104ed7bda5dSKevin Wolf case 'r': 105ed7bda5dSKevin Wolf c = '\r'; 106ed7bda5dSKevin Wolf break; 107ed7bda5dSKevin Wolf case '\\': 108ed7bda5dSKevin Wolf case '\'': 109ed7bda5dSKevin Wolf case '\"': 110ed7bda5dSKevin Wolf break; 111ed7bda5dSKevin Wolf default: 112ed7bda5dSKevin Wolf printf("unsupported escape code: '\\%c'\n", c); 113ed7bda5dSKevin Wolf goto fail; 114ed7bda5dSKevin Wolf } 115ed7bda5dSKevin Wolf if ((q - buf) < buf_size - 1) { 116ed7bda5dSKevin Wolf *q++ = c; 117ed7bda5dSKevin Wolf } 118ed7bda5dSKevin Wolf } else { 119ed7bda5dSKevin Wolf if ((q - buf) < buf_size - 1) { 120ed7bda5dSKevin Wolf *q++ = *p; 121ed7bda5dSKevin Wolf } 122ed7bda5dSKevin Wolf p++; 123ed7bda5dSKevin Wolf } 124ed7bda5dSKevin Wolf } 125ed7bda5dSKevin Wolf if (*p != '\"') { 126ed7bda5dSKevin Wolf printf("unterminated string\n"); 127ed7bda5dSKevin Wolf goto fail; 128ed7bda5dSKevin Wolf } 129ed7bda5dSKevin Wolf p++; 130ed7bda5dSKevin Wolf } else { 131ed7bda5dSKevin Wolf while (*p != '\0' && !qemu_isspace(*p)) { 132ed7bda5dSKevin Wolf if ((q - buf) < buf_size - 1) { 133ed7bda5dSKevin Wolf *q++ = *p; 134ed7bda5dSKevin Wolf } 135ed7bda5dSKevin Wolf p++; 136ed7bda5dSKevin Wolf } 137ed7bda5dSKevin Wolf } 138ed7bda5dSKevin Wolf *q = '\0'; 139ed7bda5dSKevin Wolf *pp = p; 140ed7bda5dSKevin Wolf return 0; 141ed7bda5dSKevin Wolf } 142ed7bda5dSKevin Wolf 143ed7bda5dSKevin Wolf #define MAX_ARGS 16 144ed7bda5dSKevin Wolf 145ed7bda5dSKevin Wolf static void free_cmdline_args(char **args, int nb_args) 146ed7bda5dSKevin Wolf { 147ed7bda5dSKevin Wolf int i; 148ed7bda5dSKevin Wolf 149ed7bda5dSKevin Wolf assert(nb_args <= MAX_ARGS); 150ed7bda5dSKevin Wolf 151ed7bda5dSKevin Wolf for (i = 0; i < nb_args; i++) { 152ed7bda5dSKevin Wolf g_free(args[i]); 153ed7bda5dSKevin Wolf } 154ed7bda5dSKevin Wolf 155ed7bda5dSKevin Wolf } 156ed7bda5dSKevin Wolf 157ed7bda5dSKevin Wolf /* 158ed7bda5dSKevin Wolf * Parse the command line to get valid args. 159ed7bda5dSKevin Wolf * @cmdline: command line to be parsed. 160ed7bda5dSKevin Wolf * @pnb_args: location to store the number of args, must NOT be NULL. 161ed7bda5dSKevin Wolf * @args: location to store the args, which should be freed by caller, must 162ed7bda5dSKevin Wolf * NOT be NULL. 163ed7bda5dSKevin Wolf * 164ed7bda5dSKevin Wolf * Returns 0 on success, negative on failure. 165ed7bda5dSKevin Wolf * 166ed7bda5dSKevin Wolf * NOTE: this parser is an approximate form of the real command parser. Number 167ed7bda5dSKevin Wolf * of args have a limit of MAX_ARGS. If cmdline contains more, it will 168ed7bda5dSKevin Wolf * return with failure. 169ed7bda5dSKevin Wolf */ 170ed7bda5dSKevin Wolf static int parse_cmdline(const char *cmdline, 171ed7bda5dSKevin Wolf int *pnb_args, char **args) 172ed7bda5dSKevin Wolf { 173ed7bda5dSKevin Wolf const char *p; 174ed7bda5dSKevin Wolf int nb_args, ret; 175ed7bda5dSKevin Wolf char buf[1024]; 176ed7bda5dSKevin Wolf 177ed7bda5dSKevin Wolf p = cmdline; 178ed7bda5dSKevin Wolf nb_args = 0; 179ed7bda5dSKevin Wolf for (;;) { 180ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 181ed7bda5dSKevin Wolf p++; 182ed7bda5dSKevin Wolf } 183ed7bda5dSKevin Wolf if (*p == '\0') { 184ed7bda5dSKevin Wolf break; 185ed7bda5dSKevin Wolf } 186ed7bda5dSKevin Wolf if (nb_args >= MAX_ARGS) { 187ed7bda5dSKevin Wolf goto fail; 188ed7bda5dSKevin Wolf } 189ed7bda5dSKevin Wolf ret = get_str(buf, sizeof(buf), &p); 190ed7bda5dSKevin Wolf if (ret < 0) { 191ed7bda5dSKevin Wolf goto fail; 192ed7bda5dSKevin Wolf } 193ed7bda5dSKevin Wolf args[nb_args] = g_strdup(buf); 194ed7bda5dSKevin Wolf nb_args++; 195ed7bda5dSKevin Wolf } 196ed7bda5dSKevin Wolf *pnb_args = nb_args; 197ed7bda5dSKevin Wolf return 0; 198ed7bda5dSKevin Wolf 199ed7bda5dSKevin Wolf fail: 200ed7bda5dSKevin Wolf free_cmdline_args(args, nb_args); 201ed7bda5dSKevin Wolf return -1; 202ed7bda5dSKevin Wolf } 203ed7bda5dSKevin Wolf 204ed7bda5dSKevin Wolf /* 205ed7bda5dSKevin Wolf * Can command @cmd be executed in preconfig state? 206ed7bda5dSKevin Wolf */ 207ed7bda5dSKevin Wolf static bool cmd_can_preconfig(const HMPCommand *cmd) 208ed7bda5dSKevin Wolf { 209ed7bda5dSKevin Wolf if (!cmd->flags) { 210ed7bda5dSKevin Wolf return false; 211ed7bda5dSKevin Wolf } 212ed7bda5dSKevin Wolf 213ed7bda5dSKevin Wolf return strchr(cmd->flags, 'p'); 214ed7bda5dSKevin Wolf } 215ed7bda5dSKevin Wolf 216ed7bda5dSKevin Wolf static void help_cmd_dump_one(Monitor *mon, 217ed7bda5dSKevin Wolf const HMPCommand *cmd, 218ed7bda5dSKevin Wolf char **prefix_args, 219ed7bda5dSKevin Wolf int prefix_args_nb) 220ed7bda5dSKevin Wolf { 221ed7bda5dSKevin Wolf int i; 222ed7bda5dSKevin Wolf 223ed7bda5dSKevin Wolf if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) { 224ed7bda5dSKevin Wolf return; 225ed7bda5dSKevin Wolf } 226ed7bda5dSKevin Wolf 227ed7bda5dSKevin Wolf for (i = 0; i < prefix_args_nb; i++) { 228ed7bda5dSKevin Wolf monitor_printf(mon, "%s ", prefix_args[i]); 229ed7bda5dSKevin Wolf } 230ed7bda5dSKevin Wolf monitor_printf(mon, "%s %s -- %s\n", cmd->name, cmd->params, cmd->help); 231ed7bda5dSKevin Wolf } 232ed7bda5dSKevin Wolf 233ed7bda5dSKevin Wolf /* @args[@arg_index] is the valid command need to find in @cmds */ 234ed7bda5dSKevin Wolf static void help_cmd_dump(Monitor *mon, const HMPCommand *cmds, 235ed7bda5dSKevin Wolf char **args, int nb_args, int arg_index) 236ed7bda5dSKevin Wolf { 237ed7bda5dSKevin Wolf const HMPCommand *cmd; 238ed7bda5dSKevin Wolf size_t i; 239ed7bda5dSKevin Wolf 240ed7bda5dSKevin Wolf /* No valid arg need to compare with, dump all in *cmds */ 241ed7bda5dSKevin Wolf if (arg_index >= nb_args) { 242ed7bda5dSKevin Wolf for (cmd = cmds; cmd->name != NULL; cmd++) { 243ed7bda5dSKevin Wolf help_cmd_dump_one(mon, cmd, args, arg_index); 244ed7bda5dSKevin Wolf } 245ed7bda5dSKevin Wolf return; 246ed7bda5dSKevin Wolf } 247ed7bda5dSKevin Wolf 248ed7bda5dSKevin Wolf /* Find one entry to dump */ 249ed7bda5dSKevin Wolf for (cmd = cmds; cmd->name != NULL; cmd++) { 250ed7bda5dSKevin Wolf if (hmp_compare_cmd(args[arg_index], cmd->name) && 251ed7bda5dSKevin Wolf ((!runstate_check(RUN_STATE_PRECONFIG) || 252ed7bda5dSKevin Wolf cmd_can_preconfig(cmd)))) { 253ed7bda5dSKevin Wolf if (cmd->sub_table) { 254ed7bda5dSKevin Wolf /* continue with next arg */ 255ed7bda5dSKevin Wolf help_cmd_dump(mon, cmd->sub_table, 256ed7bda5dSKevin Wolf args, nb_args, arg_index + 1); 257ed7bda5dSKevin Wolf } else { 258ed7bda5dSKevin Wolf help_cmd_dump_one(mon, cmd, args, arg_index); 259ed7bda5dSKevin Wolf } 260ed7bda5dSKevin Wolf return; 261ed7bda5dSKevin Wolf } 262ed7bda5dSKevin Wolf } 263ed7bda5dSKevin Wolf 264ed7bda5dSKevin Wolf /* Command not found */ 265ed7bda5dSKevin Wolf monitor_printf(mon, "unknown command: '"); 266ed7bda5dSKevin Wolf for (i = 0; i <= arg_index; i++) { 267ed7bda5dSKevin Wolf monitor_printf(mon, "%s%s", args[i], i == arg_index ? "'\n" : " "); 268ed7bda5dSKevin Wolf } 269ed7bda5dSKevin Wolf } 270ed7bda5dSKevin Wolf 271ed7bda5dSKevin Wolf void help_cmd(Monitor *mon, const char *name) 272ed7bda5dSKevin Wolf { 273ed7bda5dSKevin Wolf char *args[MAX_ARGS]; 274ed7bda5dSKevin Wolf int nb_args = 0; 275ed7bda5dSKevin Wolf 276ed7bda5dSKevin Wolf /* 1. parse user input */ 277ed7bda5dSKevin Wolf if (name) { 278ed7bda5dSKevin Wolf /* special case for log, directly dump and return */ 279ed7bda5dSKevin Wolf if (!strcmp(name, "log")) { 280ed7bda5dSKevin Wolf const QEMULogItem *item; 281ed7bda5dSKevin Wolf monitor_printf(mon, "Log items (comma separated):\n"); 282ed7bda5dSKevin Wolf monitor_printf(mon, "%-10s %s\n", "none", "remove all logs"); 283ed7bda5dSKevin Wolf for (item = qemu_log_items; item->mask != 0; item++) { 284ed7bda5dSKevin Wolf monitor_printf(mon, "%-10s %s\n", item->name, item->help); 285ed7bda5dSKevin Wolf } 286ed7bda5dSKevin Wolf return; 287ed7bda5dSKevin Wolf } 288ed7bda5dSKevin Wolf 289ed7bda5dSKevin Wolf if (parse_cmdline(name, &nb_args, args) < 0) { 290ed7bda5dSKevin Wolf return; 291ed7bda5dSKevin Wolf } 292ed7bda5dSKevin Wolf } 293ed7bda5dSKevin Wolf 294ed7bda5dSKevin Wolf /* 2. dump the contents according to parsed args */ 295ed7bda5dSKevin Wolf help_cmd_dump(mon, hmp_cmds, args, nb_args, 0); 296ed7bda5dSKevin Wolf 297ed7bda5dSKevin Wolf free_cmdline_args(args, nb_args); 298ed7bda5dSKevin Wolf } 299ed7bda5dSKevin Wolf 300ed7bda5dSKevin Wolf /*******************************************************************/ 301ed7bda5dSKevin Wolf 302ed7bda5dSKevin Wolf static const char *pch; 303ed7bda5dSKevin Wolf static sigjmp_buf expr_env; 304ed7bda5dSKevin Wolf 305ed7bda5dSKevin Wolf static void GCC_FMT_ATTR(2, 3) QEMU_NORETURN 306ed7bda5dSKevin Wolf expr_error(Monitor *mon, const char *fmt, ...) 307ed7bda5dSKevin Wolf { 308ed7bda5dSKevin Wolf va_list ap; 309ed7bda5dSKevin Wolf va_start(ap, fmt); 310ed7bda5dSKevin Wolf monitor_vprintf(mon, fmt, ap); 311ed7bda5dSKevin Wolf monitor_printf(mon, "\n"); 312ed7bda5dSKevin Wolf va_end(ap); 313ed7bda5dSKevin Wolf siglongjmp(expr_env, 1); 314ed7bda5dSKevin Wolf } 315ed7bda5dSKevin Wolf 316ed7bda5dSKevin Wolf static void next(void) 317ed7bda5dSKevin Wolf { 318ed7bda5dSKevin Wolf if (*pch != '\0') { 319ed7bda5dSKevin Wolf pch++; 320ed7bda5dSKevin Wolf while (qemu_isspace(*pch)) { 321ed7bda5dSKevin Wolf pch++; 322ed7bda5dSKevin Wolf } 323ed7bda5dSKevin Wolf } 324ed7bda5dSKevin Wolf } 325ed7bda5dSKevin Wolf 326ed7bda5dSKevin Wolf static int64_t expr_sum(Monitor *mon); 327ed7bda5dSKevin Wolf 328ed7bda5dSKevin Wolf static int64_t expr_unary(Monitor *mon) 329ed7bda5dSKevin Wolf { 330ed7bda5dSKevin Wolf int64_t n; 331ed7bda5dSKevin Wolf char *p; 332ed7bda5dSKevin Wolf int ret; 333ed7bda5dSKevin Wolf 334ed7bda5dSKevin Wolf switch (*pch) { 335ed7bda5dSKevin Wolf case '+': 336ed7bda5dSKevin Wolf next(); 337ed7bda5dSKevin Wolf n = expr_unary(mon); 338ed7bda5dSKevin Wolf break; 339ed7bda5dSKevin Wolf case '-': 340ed7bda5dSKevin Wolf next(); 341ed7bda5dSKevin Wolf n = -expr_unary(mon); 342ed7bda5dSKevin Wolf break; 343ed7bda5dSKevin Wolf case '~': 344ed7bda5dSKevin Wolf next(); 345ed7bda5dSKevin Wolf n = ~expr_unary(mon); 346ed7bda5dSKevin Wolf break; 347ed7bda5dSKevin Wolf case '(': 348ed7bda5dSKevin Wolf next(); 349ed7bda5dSKevin Wolf n = expr_sum(mon); 350ed7bda5dSKevin Wolf if (*pch != ')') { 351ed7bda5dSKevin Wolf expr_error(mon, "')' expected"); 352ed7bda5dSKevin Wolf } 353ed7bda5dSKevin Wolf next(); 354ed7bda5dSKevin Wolf break; 355ed7bda5dSKevin Wolf case '\'': 356ed7bda5dSKevin Wolf pch++; 357ed7bda5dSKevin Wolf if (*pch == '\0') { 358ed7bda5dSKevin Wolf expr_error(mon, "character constant expected"); 359ed7bda5dSKevin Wolf } 360ed7bda5dSKevin Wolf n = *pch; 361ed7bda5dSKevin Wolf pch++; 362ed7bda5dSKevin Wolf if (*pch != '\'') { 363ed7bda5dSKevin Wolf expr_error(mon, "missing terminating \' character"); 364ed7bda5dSKevin Wolf } 365ed7bda5dSKevin Wolf next(); 366ed7bda5dSKevin Wolf break; 367ed7bda5dSKevin Wolf case '$': 368ed7bda5dSKevin Wolf { 369ed7bda5dSKevin Wolf char buf[128], *q; 370ed7bda5dSKevin Wolf int64_t reg = 0; 371ed7bda5dSKevin Wolf 372ed7bda5dSKevin Wolf pch++; 373ed7bda5dSKevin Wolf q = buf; 374ed7bda5dSKevin Wolf while ((*pch >= 'a' && *pch <= 'z') || 375ed7bda5dSKevin Wolf (*pch >= 'A' && *pch <= 'Z') || 376ed7bda5dSKevin Wolf (*pch >= '0' && *pch <= '9') || 377ed7bda5dSKevin Wolf *pch == '_' || *pch == '.') { 378ed7bda5dSKevin Wolf if ((q - buf) < sizeof(buf) - 1) { 379ed7bda5dSKevin Wolf *q++ = *pch; 380ed7bda5dSKevin Wolf } 381ed7bda5dSKevin Wolf pch++; 382ed7bda5dSKevin Wolf } 383ed7bda5dSKevin Wolf while (qemu_isspace(*pch)) { 384ed7bda5dSKevin Wolf pch++; 385ed7bda5dSKevin Wolf } 386ed7bda5dSKevin Wolf *q = 0; 387ed7bda5dSKevin Wolf ret = get_monitor_def(®, buf); 388ed7bda5dSKevin Wolf if (ret < 0) { 389ed7bda5dSKevin Wolf expr_error(mon, "unknown register"); 390ed7bda5dSKevin Wolf } 391ed7bda5dSKevin Wolf n = reg; 392ed7bda5dSKevin Wolf } 393ed7bda5dSKevin Wolf break; 394ed7bda5dSKevin Wolf case '\0': 395ed7bda5dSKevin Wolf expr_error(mon, "unexpected end of expression"); 396ed7bda5dSKevin Wolf n = 0; 397ed7bda5dSKevin Wolf break; 398ed7bda5dSKevin Wolf default: 399ed7bda5dSKevin Wolf errno = 0; 400ed7bda5dSKevin Wolf n = strtoull(pch, &p, 0); 401ed7bda5dSKevin Wolf if (errno == ERANGE) { 402ed7bda5dSKevin Wolf expr_error(mon, "number too large"); 403ed7bda5dSKevin Wolf } 404ed7bda5dSKevin Wolf if (pch == p) { 405ed7bda5dSKevin Wolf expr_error(mon, "invalid char '%c' in expression", *p); 406ed7bda5dSKevin Wolf } 407ed7bda5dSKevin Wolf pch = p; 408ed7bda5dSKevin Wolf while (qemu_isspace(*pch)) { 409ed7bda5dSKevin Wolf pch++; 410ed7bda5dSKevin Wolf } 411ed7bda5dSKevin Wolf break; 412ed7bda5dSKevin Wolf } 413ed7bda5dSKevin Wolf return n; 414ed7bda5dSKevin Wolf } 415ed7bda5dSKevin Wolf 416ed7bda5dSKevin Wolf static int64_t expr_prod(Monitor *mon) 417ed7bda5dSKevin Wolf { 418ed7bda5dSKevin Wolf int64_t val, val2; 419ed7bda5dSKevin Wolf int op; 420ed7bda5dSKevin Wolf 421ed7bda5dSKevin Wolf val = expr_unary(mon); 422ed7bda5dSKevin Wolf for (;;) { 423ed7bda5dSKevin Wolf op = *pch; 424ed7bda5dSKevin Wolf if (op != '*' && op != '/' && op != '%') { 425ed7bda5dSKevin Wolf break; 426ed7bda5dSKevin Wolf } 427ed7bda5dSKevin Wolf next(); 428ed7bda5dSKevin Wolf val2 = expr_unary(mon); 429ed7bda5dSKevin Wolf switch (op) { 430ed7bda5dSKevin Wolf default: 431ed7bda5dSKevin Wolf case '*': 432ed7bda5dSKevin Wolf val *= val2; 433ed7bda5dSKevin Wolf break; 434ed7bda5dSKevin Wolf case '/': 435ed7bda5dSKevin Wolf case '%': 436ed7bda5dSKevin Wolf if (val2 == 0) { 437ed7bda5dSKevin Wolf expr_error(mon, "division by zero"); 438ed7bda5dSKevin Wolf } 439ed7bda5dSKevin Wolf if (op == '/') { 440ed7bda5dSKevin Wolf val /= val2; 441ed7bda5dSKevin Wolf } else { 442ed7bda5dSKevin Wolf val %= val2; 443ed7bda5dSKevin Wolf } 444ed7bda5dSKevin Wolf break; 445ed7bda5dSKevin Wolf } 446ed7bda5dSKevin Wolf } 447ed7bda5dSKevin Wolf return val; 448ed7bda5dSKevin Wolf } 449ed7bda5dSKevin Wolf 450ed7bda5dSKevin Wolf static int64_t expr_logic(Monitor *mon) 451ed7bda5dSKevin Wolf { 452ed7bda5dSKevin Wolf int64_t val, val2; 453ed7bda5dSKevin Wolf int op; 454ed7bda5dSKevin Wolf 455ed7bda5dSKevin Wolf val = expr_prod(mon); 456ed7bda5dSKevin Wolf for (;;) { 457ed7bda5dSKevin Wolf op = *pch; 458ed7bda5dSKevin Wolf if (op != '&' && op != '|' && op != '^') { 459ed7bda5dSKevin Wolf break; 460ed7bda5dSKevin Wolf } 461ed7bda5dSKevin Wolf next(); 462ed7bda5dSKevin Wolf val2 = expr_prod(mon); 463ed7bda5dSKevin Wolf switch (op) { 464ed7bda5dSKevin Wolf default: 465ed7bda5dSKevin Wolf case '&': 466ed7bda5dSKevin Wolf val &= val2; 467ed7bda5dSKevin Wolf break; 468ed7bda5dSKevin Wolf case '|': 469ed7bda5dSKevin Wolf val |= val2; 470ed7bda5dSKevin Wolf break; 471ed7bda5dSKevin Wolf case '^': 472ed7bda5dSKevin Wolf val ^= val2; 473ed7bda5dSKevin Wolf break; 474ed7bda5dSKevin Wolf } 475ed7bda5dSKevin Wolf } 476ed7bda5dSKevin Wolf return val; 477ed7bda5dSKevin Wolf } 478ed7bda5dSKevin Wolf 479ed7bda5dSKevin Wolf static int64_t expr_sum(Monitor *mon) 480ed7bda5dSKevin Wolf { 481ed7bda5dSKevin Wolf int64_t val, val2; 482ed7bda5dSKevin Wolf int op; 483ed7bda5dSKevin Wolf 484ed7bda5dSKevin Wolf val = expr_logic(mon); 485ed7bda5dSKevin Wolf for (;;) { 486ed7bda5dSKevin Wolf op = *pch; 487ed7bda5dSKevin Wolf if (op != '+' && op != '-') { 488ed7bda5dSKevin Wolf break; 489ed7bda5dSKevin Wolf } 490ed7bda5dSKevin Wolf next(); 491ed7bda5dSKevin Wolf val2 = expr_logic(mon); 492ed7bda5dSKevin Wolf if (op == '+') { 493ed7bda5dSKevin Wolf val += val2; 494ed7bda5dSKevin Wolf } else { 495ed7bda5dSKevin Wolf val -= val2; 496ed7bda5dSKevin Wolf } 497ed7bda5dSKevin Wolf } 498ed7bda5dSKevin Wolf return val; 499ed7bda5dSKevin Wolf } 500ed7bda5dSKevin Wolf 501ed7bda5dSKevin Wolf static int get_expr(Monitor *mon, int64_t *pval, const char **pp) 502ed7bda5dSKevin Wolf { 503ed7bda5dSKevin Wolf pch = *pp; 504ed7bda5dSKevin Wolf if (sigsetjmp(expr_env, 0)) { 505ed7bda5dSKevin Wolf *pp = pch; 506ed7bda5dSKevin Wolf return -1; 507ed7bda5dSKevin Wolf } 508ed7bda5dSKevin Wolf while (qemu_isspace(*pch)) { 509ed7bda5dSKevin Wolf pch++; 510ed7bda5dSKevin Wolf } 511ed7bda5dSKevin Wolf *pval = expr_sum(mon); 512ed7bda5dSKevin Wolf *pp = pch; 513ed7bda5dSKevin Wolf return 0; 514ed7bda5dSKevin Wolf } 515ed7bda5dSKevin Wolf 516ed7bda5dSKevin Wolf static int get_double(Monitor *mon, double *pval, const char **pp) 517ed7bda5dSKevin Wolf { 518ed7bda5dSKevin Wolf const char *p = *pp; 519ed7bda5dSKevin Wolf char *tailp; 520ed7bda5dSKevin Wolf double d; 521ed7bda5dSKevin Wolf 522ed7bda5dSKevin Wolf d = strtod(p, &tailp); 523ed7bda5dSKevin Wolf if (tailp == p) { 524ed7bda5dSKevin Wolf monitor_printf(mon, "Number expected\n"); 525ed7bda5dSKevin Wolf return -1; 526ed7bda5dSKevin Wolf } 527ed7bda5dSKevin Wolf if (d != d || d - d != 0) { 528ed7bda5dSKevin Wolf /* NaN or infinity */ 529ed7bda5dSKevin Wolf monitor_printf(mon, "Bad number\n"); 530ed7bda5dSKevin Wolf return -1; 531ed7bda5dSKevin Wolf } 532ed7bda5dSKevin Wolf *pval = d; 533ed7bda5dSKevin Wolf *pp = tailp; 534ed7bda5dSKevin Wolf return 0; 535ed7bda5dSKevin Wolf } 536ed7bda5dSKevin Wolf 537ed7bda5dSKevin Wolf /* 538ed7bda5dSKevin Wolf * Store the command-name in cmdname, and return a pointer to 539ed7bda5dSKevin Wolf * the remaining of the command string. 540ed7bda5dSKevin Wolf */ 541ed7bda5dSKevin Wolf static const char *get_command_name(const char *cmdline, 542ed7bda5dSKevin Wolf char *cmdname, size_t nlen) 543ed7bda5dSKevin Wolf { 544ed7bda5dSKevin Wolf size_t len; 545ed7bda5dSKevin Wolf const char *p, *pstart; 546ed7bda5dSKevin Wolf 547ed7bda5dSKevin Wolf p = cmdline; 548ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 549ed7bda5dSKevin Wolf p++; 550ed7bda5dSKevin Wolf } 551ed7bda5dSKevin Wolf if (*p == '\0') { 552ed7bda5dSKevin Wolf return NULL; 553ed7bda5dSKevin Wolf } 554ed7bda5dSKevin Wolf pstart = p; 555ed7bda5dSKevin Wolf while (*p != '\0' && *p != '/' && !qemu_isspace(*p)) { 556ed7bda5dSKevin Wolf p++; 557ed7bda5dSKevin Wolf } 558ed7bda5dSKevin Wolf len = p - pstart; 559ed7bda5dSKevin Wolf if (len > nlen - 1) { 560ed7bda5dSKevin Wolf len = nlen - 1; 561ed7bda5dSKevin Wolf } 562ed7bda5dSKevin Wolf memcpy(cmdname, pstart, len); 563ed7bda5dSKevin Wolf cmdname[len] = '\0'; 564ed7bda5dSKevin Wolf return p; 565ed7bda5dSKevin Wolf } 566ed7bda5dSKevin Wolf 567ed7bda5dSKevin Wolf /** 568ed7bda5dSKevin Wolf * Read key of 'type' into 'key' and return the current 569ed7bda5dSKevin Wolf * 'type' pointer. 570ed7bda5dSKevin Wolf */ 571ed7bda5dSKevin Wolf static char *key_get_info(const char *type, char **key) 572ed7bda5dSKevin Wolf { 573ed7bda5dSKevin Wolf size_t len; 574ed7bda5dSKevin Wolf char *p, *str; 575ed7bda5dSKevin Wolf 576ed7bda5dSKevin Wolf if (*type == ',') { 577ed7bda5dSKevin Wolf type++; 578ed7bda5dSKevin Wolf } 579ed7bda5dSKevin Wolf 580ed7bda5dSKevin Wolf p = strchr(type, ':'); 581ed7bda5dSKevin Wolf if (!p) { 582ed7bda5dSKevin Wolf *key = NULL; 583ed7bda5dSKevin Wolf return NULL; 584ed7bda5dSKevin Wolf } 585ed7bda5dSKevin Wolf len = p - type; 586ed7bda5dSKevin Wolf 587ed7bda5dSKevin Wolf str = g_malloc(len + 1); 588ed7bda5dSKevin Wolf memcpy(str, type, len); 589ed7bda5dSKevin Wolf str[len] = '\0'; 590ed7bda5dSKevin Wolf 591ed7bda5dSKevin Wolf *key = str; 592ed7bda5dSKevin Wolf return ++p; 593ed7bda5dSKevin Wolf } 594ed7bda5dSKevin Wolf 595ed7bda5dSKevin Wolf static int default_fmt_format = 'x'; 596ed7bda5dSKevin Wolf static int default_fmt_size = 4; 597ed7bda5dSKevin Wolf 598ed7bda5dSKevin Wolf static int is_valid_option(const char *c, const char *typestr) 599ed7bda5dSKevin Wolf { 600ed7bda5dSKevin Wolf char option[3]; 601ed7bda5dSKevin Wolf 602ed7bda5dSKevin Wolf option[0] = '-'; 603ed7bda5dSKevin Wolf option[1] = *c; 604ed7bda5dSKevin Wolf option[2] = '\0'; 605ed7bda5dSKevin Wolf 606ed7bda5dSKevin Wolf typestr = strstr(typestr, option); 607ed7bda5dSKevin Wolf return (typestr != NULL); 608ed7bda5dSKevin Wolf } 609ed7bda5dSKevin Wolf 610ed7bda5dSKevin Wolf static const HMPCommand *search_dispatch_table(const HMPCommand *disp_table, 611ed7bda5dSKevin Wolf const char *cmdname) 612ed7bda5dSKevin Wolf { 613ed7bda5dSKevin Wolf const HMPCommand *cmd; 614ed7bda5dSKevin Wolf 615ed7bda5dSKevin Wolf for (cmd = disp_table; cmd->name != NULL; cmd++) { 616ed7bda5dSKevin Wolf if (hmp_compare_cmd(cmdname, cmd->name)) { 617ed7bda5dSKevin Wolf return cmd; 618ed7bda5dSKevin Wolf } 619ed7bda5dSKevin Wolf } 620ed7bda5dSKevin Wolf 621ed7bda5dSKevin Wolf return NULL; 622ed7bda5dSKevin Wolf } 623ed7bda5dSKevin Wolf 624ed7bda5dSKevin Wolf /* 625ed7bda5dSKevin Wolf * Parse command name from @cmdp according to command table @table. 626ed7bda5dSKevin Wolf * If blank, return NULL. 627ed7bda5dSKevin Wolf * Else, if no valid command can be found, report to @mon, and return 628ed7bda5dSKevin Wolf * NULL. 629ed7bda5dSKevin Wolf * Else, change @cmdp to point right behind the name, and return its 630ed7bda5dSKevin Wolf * command table entry. 631ed7bda5dSKevin Wolf * Do not assume the return value points into @table! It doesn't when 632ed7bda5dSKevin Wolf * the command is found in a sub-command table. 633ed7bda5dSKevin Wolf */ 634ed7bda5dSKevin Wolf static const HMPCommand *monitor_parse_command(MonitorHMP *hmp_mon, 635ed7bda5dSKevin Wolf const char *cmdp_start, 636ed7bda5dSKevin Wolf const char **cmdp, 637ed7bda5dSKevin Wolf HMPCommand *table) 638ed7bda5dSKevin Wolf { 639ed7bda5dSKevin Wolf Monitor *mon = &hmp_mon->common; 640ed7bda5dSKevin Wolf const char *p; 641ed7bda5dSKevin Wolf const HMPCommand *cmd; 642ed7bda5dSKevin Wolf char cmdname[256]; 643ed7bda5dSKevin Wolf 644ed7bda5dSKevin Wolf /* extract the command name */ 645ed7bda5dSKevin Wolf p = get_command_name(*cmdp, cmdname, sizeof(cmdname)); 646ed7bda5dSKevin Wolf if (!p) { 647ed7bda5dSKevin Wolf return NULL; 648ed7bda5dSKevin Wolf } 649ed7bda5dSKevin Wolf 650ed7bda5dSKevin Wolf cmd = search_dispatch_table(table, cmdname); 651ed7bda5dSKevin Wolf if (!cmd) { 652ed7bda5dSKevin Wolf monitor_printf(mon, "unknown command: '%.*s'\n", 653ed7bda5dSKevin Wolf (int)(p - cmdp_start), cmdp_start); 654ed7bda5dSKevin Wolf return NULL; 655ed7bda5dSKevin Wolf } 656ed7bda5dSKevin Wolf if (runstate_check(RUN_STATE_PRECONFIG) && !cmd_can_preconfig(cmd)) { 657ed7bda5dSKevin Wolf monitor_printf(mon, "Command '%.*s' not available with -preconfig " 658ed7bda5dSKevin Wolf "until after exit_preconfig.\n", 659ed7bda5dSKevin Wolf (int)(p - cmdp_start), cmdp_start); 660ed7bda5dSKevin Wolf return NULL; 661ed7bda5dSKevin Wolf } 662ed7bda5dSKevin Wolf 663ed7bda5dSKevin Wolf /* filter out following useless space */ 664ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 665ed7bda5dSKevin Wolf p++; 666ed7bda5dSKevin Wolf } 667ed7bda5dSKevin Wolf 668ed7bda5dSKevin Wolf *cmdp = p; 669ed7bda5dSKevin Wolf /* search sub command */ 670ed7bda5dSKevin Wolf if (cmd->sub_table != NULL && *p != '\0') { 671ed7bda5dSKevin Wolf return monitor_parse_command(hmp_mon, cmdp_start, cmdp, cmd->sub_table); 672ed7bda5dSKevin Wolf } 673ed7bda5dSKevin Wolf 674ed7bda5dSKevin Wolf return cmd; 675ed7bda5dSKevin Wolf } 676ed7bda5dSKevin Wolf 677ed7bda5dSKevin Wolf /* 678ed7bda5dSKevin Wolf * Parse arguments for @cmd. 679ed7bda5dSKevin Wolf * If it can't be parsed, report to @mon, and return NULL. 680ed7bda5dSKevin Wolf * Else, insert command arguments into a QDict, and return it. 681ed7bda5dSKevin Wolf * Note: On success, caller has to free the QDict structure. 682ed7bda5dSKevin Wolf */ 683ed7bda5dSKevin Wolf static QDict *monitor_parse_arguments(Monitor *mon, 684ed7bda5dSKevin Wolf const char **endp, 685ed7bda5dSKevin Wolf const HMPCommand *cmd) 686ed7bda5dSKevin Wolf { 687ed7bda5dSKevin Wolf const char *typestr; 688ed7bda5dSKevin Wolf char *key; 689ed7bda5dSKevin Wolf int c; 690ed7bda5dSKevin Wolf const char *p = *endp; 691ed7bda5dSKevin Wolf char buf[1024]; 692ed7bda5dSKevin Wolf QDict *qdict = qdict_new(); 693ed7bda5dSKevin Wolf 694ed7bda5dSKevin Wolf /* parse the parameters */ 695ed7bda5dSKevin Wolf typestr = cmd->args_type; 696ed7bda5dSKevin Wolf for (;;) { 697ed7bda5dSKevin Wolf typestr = key_get_info(typestr, &key); 698ed7bda5dSKevin Wolf if (!typestr) { 699ed7bda5dSKevin Wolf break; 700ed7bda5dSKevin Wolf } 701ed7bda5dSKevin Wolf c = *typestr; 702ed7bda5dSKevin Wolf typestr++; 703ed7bda5dSKevin Wolf switch (c) { 704ed7bda5dSKevin Wolf case 'F': 705ed7bda5dSKevin Wolf case 'B': 706ed7bda5dSKevin Wolf case 's': 707ed7bda5dSKevin Wolf { 708ed7bda5dSKevin Wolf int ret; 709ed7bda5dSKevin Wolf 710ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 711ed7bda5dSKevin Wolf p++; 712ed7bda5dSKevin Wolf } 713ed7bda5dSKevin Wolf if (*typestr == '?') { 714ed7bda5dSKevin Wolf typestr++; 715ed7bda5dSKevin Wolf if (*p == '\0') { 716ed7bda5dSKevin Wolf /* no optional string: NULL argument */ 717ed7bda5dSKevin Wolf break; 718ed7bda5dSKevin Wolf } 719ed7bda5dSKevin Wolf } 720ed7bda5dSKevin Wolf ret = get_str(buf, sizeof(buf), &p); 721ed7bda5dSKevin Wolf if (ret < 0) { 722ed7bda5dSKevin Wolf switch (c) { 723ed7bda5dSKevin Wolf case 'F': 724ed7bda5dSKevin Wolf monitor_printf(mon, "%s: filename expected\n", 725ed7bda5dSKevin Wolf cmd->name); 726ed7bda5dSKevin Wolf break; 727ed7bda5dSKevin Wolf case 'B': 728ed7bda5dSKevin Wolf monitor_printf(mon, "%s: block device name expected\n", 729ed7bda5dSKevin Wolf cmd->name); 730ed7bda5dSKevin Wolf break; 731ed7bda5dSKevin Wolf default: 732ed7bda5dSKevin Wolf monitor_printf(mon, "%s: string expected\n", cmd->name); 733ed7bda5dSKevin Wolf break; 734ed7bda5dSKevin Wolf } 735ed7bda5dSKevin Wolf goto fail; 736ed7bda5dSKevin Wolf } 737ed7bda5dSKevin Wolf qdict_put_str(qdict, key, buf); 738ed7bda5dSKevin Wolf } 739ed7bda5dSKevin Wolf break; 740ed7bda5dSKevin Wolf case 'O': 741ed7bda5dSKevin Wolf { 742ed7bda5dSKevin Wolf QemuOptsList *opts_list; 743ed7bda5dSKevin Wolf QemuOpts *opts; 744ed7bda5dSKevin Wolf 745ed7bda5dSKevin Wolf opts_list = qemu_find_opts(key); 746ed7bda5dSKevin Wolf if (!opts_list || opts_list->desc->name) { 747ed7bda5dSKevin Wolf goto bad_type; 748ed7bda5dSKevin Wolf } 749ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 750ed7bda5dSKevin Wolf p++; 751ed7bda5dSKevin Wolf } 752ed7bda5dSKevin Wolf if (!*p) { 753ed7bda5dSKevin Wolf break; 754ed7bda5dSKevin Wolf } 755ed7bda5dSKevin Wolf if (get_str(buf, sizeof(buf), &p) < 0) { 756ed7bda5dSKevin Wolf goto fail; 757ed7bda5dSKevin Wolf } 758ed7bda5dSKevin Wolf opts = qemu_opts_parse_noisily(opts_list, buf, true); 759ed7bda5dSKevin Wolf if (!opts) { 760ed7bda5dSKevin Wolf goto fail; 761ed7bda5dSKevin Wolf } 762ed7bda5dSKevin Wolf qemu_opts_to_qdict(opts, qdict); 763ed7bda5dSKevin Wolf qemu_opts_del(opts); 764ed7bda5dSKevin Wolf } 765ed7bda5dSKevin Wolf break; 766ed7bda5dSKevin Wolf case '/': 767ed7bda5dSKevin Wolf { 768ed7bda5dSKevin Wolf int count, format, size; 769ed7bda5dSKevin Wolf 770ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 771ed7bda5dSKevin Wolf p++; 772ed7bda5dSKevin Wolf } 773ed7bda5dSKevin Wolf if (*p == '/') { 774ed7bda5dSKevin Wolf /* format found */ 775ed7bda5dSKevin Wolf p++; 776ed7bda5dSKevin Wolf count = 1; 777ed7bda5dSKevin Wolf if (qemu_isdigit(*p)) { 778ed7bda5dSKevin Wolf count = 0; 779ed7bda5dSKevin Wolf while (qemu_isdigit(*p)) { 780ed7bda5dSKevin Wolf count = count * 10 + (*p - '0'); 781ed7bda5dSKevin Wolf p++; 782ed7bda5dSKevin Wolf } 783ed7bda5dSKevin Wolf } 784ed7bda5dSKevin Wolf size = -1; 785ed7bda5dSKevin Wolf format = -1; 786ed7bda5dSKevin Wolf for (;;) { 787ed7bda5dSKevin Wolf switch (*p) { 788ed7bda5dSKevin Wolf case 'o': 789ed7bda5dSKevin Wolf case 'd': 790ed7bda5dSKevin Wolf case 'u': 791ed7bda5dSKevin Wolf case 'x': 792ed7bda5dSKevin Wolf case 'i': 793ed7bda5dSKevin Wolf case 'c': 794ed7bda5dSKevin Wolf format = *p++; 795ed7bda5dSKevin Wolf break; 796ed7bda5dSKevin Wolf case 'b': 797ed7bda5dSKevin Wolf size = 1; 798ed7bda5dSKevin Wolf p++; 799ed7bda5dSKevin Wolf break; 800ed7bda5dSKevin Wolf case 'h': 801ed7bda5dSKevin Wolf size = 2; 802ed7bda5dSKevin Wolf p++; 803ed7bda5dSKevin Wolf break; 804ed7bda5dSKevin Wolf case 'w': 805ed7bda5dSKevin Wolf size = 4; 806ed7bda5dSKevin Wolf p++; 807ed7bda5dSKevin Wolf break; 808ed7bda5dSKevin Wolf case 'g': 809ed7bda5dSKevin Wolf case 'L': 810ed7bda5dSKevin Wolf size = 8; 811ed7bda5dSKevin Wolf p++; 812ed7bda5dSKevin Wolf break; 813ed7bda5dSKevin Wolf default: 814ed7bda5dSKevin Wolf goto next; 815ed7bda5dSKevin Wolf } 816ed7bda5dSKevin Wolf } 817ed7bda5dSKevin Wolf next: 818ed7bda5dSKevin Wolf if (*p != '\0' && !qemu_isspace(*p)) { 819ed7bda5dSKevin Wolf monitor_printf(mon, "invalid char in format: '%c'\n", 820ed7bda5dSKevin Wolf *p); 821ed7bda5dSKevin Wolf goto fail; 822ed7bda5dSKevin Wolf } 823ed7bda5dSKevin Wolf if (format < 0) { 824ed7bda5dSKevin Wolf format = default_fmt_format; 825ed7bda5dSKevin Wolf } 826ed7bda5dSKevin Wolf if (format != 'i') { 827ed7bda5dSKevin Wolf /* for 'i', not specifying a size gives -1 as size */ 828ed7bda5dSKevin Wolf if (size < 0) { 829ed7bda5dSKevin Wolf size = default_fmt_size; 830ed7bda5dSKevin Wolf } 831ed7bda5dSKevin Wolf default_fmt_size = size; 832ed7bda5dSKevin Wolf } 833ed7bda5dSKevin Wolf default_fmt_format = format; 834ed7bda5dSKevin Wolf } else { 835ed7bda5dSKevin Wolf count = 1; 836ed7bda5dSKevin Wolf format = default_fmt_format; 837ed7bda5dSKevin Wolf if (format != 'i') { 838ed7bda5dSKevin Wolf size = default_fmt_size; 839ed7bda5dSKevin Wolf } else { 840ed7bda5dSKevin Wolf size = -1; 841ed7bda5dSKevin Wolf } 842ed7bda5dSKevin Wolf } 843ed7bda5dSKevin Wolf qdict_put_int(qdict, "count", count); 844ed7bda5dSKevin Wolf qdict_put_int(qdict, "format", format); 845ed7bda5dSKevin Wolf qdict_put_int(qdict, "size", size); 846ed7bda5dSKevin Wolf } 847ed7bda5dSKevin Wolf break; 848ed7bda5dSKevin Wolf case 'i': 849ed7bda5dSKevin Wolf case 'l': 850ed7bda5dSKevin Wolf case 'M': 851ed7bda5dSKevin Wolf { 852ed7bda5dSKevin Wolf int64_t val; 853ed7bda5dSKevin Wolf 854ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 855ed7bda5dSKevin Wolf p++; 856ed7bda5dSKevin Wolf } 857ed7bda5dSKevin Wolf if (*typestr == '?' || *typestr == '.') { 858ed7bda5dSKevin Wolf if (*typestr == '?') { 859ed7bda5dSKevin Wolf if (*p == '\0') { 860ed7bda5dSKevin Wolf typestr++; 861ed7bda5dSKevin Wolf break; 862ed7bda5dSKevin Wolf } 863ed7bda5dSKevin Wolf } else { 864ed7bda5dSKevin Wolf if (*p == '.') { 865ed7bda5dSKevin Wolf p++; 866ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 867ed7bda5dSKevin Wolf p++; 868ed7bda5dSKevin Wolf } 869ed7bda5dSKevin Wolf } else { 870ed7bda5dSKevin Wolf typestr++; 871ed7bda5dSKevin Wolf break; 872ed7bda5dSKevin Wolf } 873ed7bda5dSKevin Wolf } 874ed7bda5dSKevin Wolf typestr++; 875ed7bda5dSKevin Wolf } 876ed7bda5dSKevin Wolf if (get_expr(mon, &val, &p)) { 877ed7bda5dSKevin Wolf goto fail; 878ed7bda5dSKevin Wolf } 879ed7bda5dSKevin Wolf /* Check if 'i' is greater than 32-bit */ 880ed7bda5dSKevin Wolf if ((c == 'i') && ((val >> 32) & 0xffffffff)) { 881ed7bda5dSKevin Wolf monitor_printf(mon, "\'%s\' has failed: ", cmd->name); 882ed7bda5dSKevin Wolf monitor_printf(mon, "integer is for 32-bit values\n"); 883ed7bda5dSKevin Wolf goto fail; 884ed7bda5dSKevin Wolf } else if (c == 'M') { 885ed7bda5dSKevin Wolf if (val < 0) { 886ed7bda5dSKevin Wolf monitor_printf(mon, "enter a positive value\n"); 887ed7bda5dSKevin Wolf goto fail; 888ed7bda5dSKevin Wolf } 889ed7bda5dSKevin Wolf val *= MiB; 890ed7bda5dSKevin Wolf } 891ed7bda5dSKevin Wolf qdict_put_int(qdict, key, val); 892ed7bda5dSKevin Wolf } 893ed7bda5dSKevin Wolf break; 894ed7bda5dSKevin Wolf case 'o': 895ed7bda5dSKevin Wolf { 896ed7bda5dSKevin Wolf int ret; 897ed7bda5dSKevin Wolf uint64_t val; 898ed7bda5dSKevin Wolf const char *end; 899ed7bda5dSKevin Wolf 900ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 901ed7bda5dSKevin Wolf p++; 902ed7bda5dSKevin Wolf } 903ed7bda5dSKevin Wolf if (*typestr == '?') { 904ed7bda5dSKevin Wolf typestr++; 905ed7bda5dSKevin Wolf if (*p == '\0') { 906ed7bda5dSKevin Wolf break; 907ed7bda5dSKevin Wolf } 908ed7bda5dSKevin Wolf } 909ed7bda5dSKevin Wolf ret = qemu_strtosz_MiB(p, &end, &val); 910ed7bda5dSKevin Wolf if (ret < 0 || val > INT64_MAX) { 911ed7bda5dSKevin Wolf monitor_printf(mon, "invalid size\n"); 912ed7bda5dSKevin Wolf goto fail; 913ed7bda5dSKevin Wolf } 914ed7bda5dSKevin Wolf qdict_put_int(qdict, key, val); 915ed7bda5dSKevin Wolf p = end; 916ed7bda5dSKevin Wolf } 917ed7bda5dSKevin Wolf break; 918ed7bda5dSKevin Wolf case 'T': 919ed7bda5dSKevin Wolf { 920ed7bda5dSKevin Wolf double val; 921ed7bda5dSKevin Wolf 922ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 923ed7bda5dSKevin Wolf p++; 924ed7bda5dSKevin Wolf } 925ed7bda5dSKevin Wolf if (*typestr == '?') { 926ed7bda5dSKevin Wolf typestr++; 927ed7bda5dSKevin Wolf if (*p == '\0') { 928ed7bda5dSKevin Wolf break; 929ed7bda5dSKevin Wolf } 930ed7bda5dSKevin Wolf } 931ed7bda5dSKevin Wolf if (get_double(mon, &val, &p) < 0) { 932ed7bda5dSKevin Wolf goto fail; 933ed7bda5dSKevin Wolf } 934ed7bda5dSKevin Wolf if (p[0] && p[1] == 's') { 935ed7bda5dSKevin Wolf switch (*p) { 936ed7bda5dSKevin Wolf case 'm': 937ed7bda5dSKevin Wolf val /= 1e3; p += 2; break; 938ed7bda5dSKevin Wolf case 'u': 939ed7bda5dSKevin Wolf val /= 1e6; p += 2; break; 940ed7bda5dSKevin Wolf case 'n': 941ed7bda5dSKevin Wolf val /= 1e9; p += 2; break; 942ed7bda5dSKevin Wolf } 943ed7bda5dSKevin Wolf } 944ed7bda5dSKevin Wolf if (*p && !qemu_isspace(*p)) { 945ed7bda5dSKevin Wolf monitor_printf(mon, "Unknown unit suffix\n"); 946ed7bda5dSKevin Wolf goto fail; 947ed7bda5dSKevin Wolf } 948ed7bda5dSKevin Wolf qdict_put(qdict, key, qnum_from_double(val)); 949ed7bda5dSKevin Wolf } 950ed7bda5dSKevin Wolf break; 951ed7bda5dSKevin Wolf case 'b': 952ed7bda5dSKevin Wolf { 953ed7bda5dSKevin Wolf const char *beg; 954ed7bda5dSKevin Wolf bool val; 955ed7bda5dSKevin Wolf 956ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 957ed7bda5dSKevin Wolf p++; 958ed7bda5dSKevin Wolf } 959ed7bda5dSKevin Wolf beg = p; 960ed7bda5dSKevin Wolf while (qemu_isgraph(*p)) { 961ed7bda5dSKevin Wolf p++; 962ed7bda5dSKevin Wolf } 963ed7bda5dSKevin Wolf if (p - beg == 2 && !memcmp(beg, "on", p - beg)) { 964ed7bda5dSKevin Wolf val = true; 965ed7bda5dSKevin Wolf } else if (p - beg == 3 && !memcmp(beg, "off", p - beg)) { 966ed7bda5dSKevin Wolf val = false; 967ed7bda5dSKevin Wolf } else { 968ed7bda5dSKevin Wolf monitor_printf(mon, "Expected 'on' or 'off'\n"); 969ed7bda5dSKevin Wolf goto fail; 970ed7bda5dSKevin Wolf } 971ed7bda5dSKevin Wolf qdict_put_bool(qdict, key, val); 972ed7bda5dSKevin Wolf } 973ed7bda5dSKevin Wolf break; 974ed7bda5dSKevin Wolf case '-': 975ed7bda5dSKevin Wolf { 976ed7bda5dSKevin Wolf const char *tmp = p; 977ed7bda5dSKevin Wolf int skip_key = 0; 978ed7bda5dSKevin Wolf /* option */ 979ed7bda5dSKevin Wolf 980ed7bda5dSKevin Wolf c = *typestr++; 981ed7bda5dSKevin Wolf if (c == '\0') { 982ed7bda5dSKevin Wolf goto bad_type; 983ed7bda5dSKevin Wolf } 984ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 985ed7bda5dSKevin Wolf p++; 986ed7bda5dSKevin Wolf } 987ed7bda5dSKevin Wolf if (*p == '-') { 988ed7bda5dSKevin Wolf p++; 989ed7bda5dSKevin Wolf if (c != *p) { 990ed7bda5dSKevin Wolf if (!is_valid_option(p, typestr)) { 991ed7bda5dSKevin Wolf monitor_printf(mon, "%s: unsupported option -%c\n", 992ed7bda5dSKevin Wolf cmd->name, *p); 993ed7bda5dSKevin Wolf goto fail; 994ed7bda5dSKevin Wolf } else { 995ed7bda5dSKevin Wolf skip_key = 1; 996ed7bda5dSKevin Wolf } 997ed7bda5dSKevin Wolf } 998ed7bda5dSKevin Wolf if (skip_key) { 999ed7bda5dSKevin Wolf p = tmp; 1000ed7bda5dSKevin Wolf } else { 1001ed7bda5dSKevin Wolf /* has option */ 1002ed7bda5dSKevin Wolf p++; 1003ed7bda5dSKevin Wolf qdict_put_bool(qdict, key, true); 1004ed7bda5dSKevin Wolf } 1005ed7bda5dSKevin Wolf } 1006ed7bda5dSKevin Wolf } 1007ed7bda5dSKevin Wolf break; 1008ed7bda5dSKevin Wolf case 'S': 1009ed7bda5dSKevin Wolf { 1010ed7bda5dSKevin Wolf /* package all remaining string */ 1011ed7bda5dSKevin Wolf int len; 1012ed7bda5dSKevin Wolf 1013ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 1014ed7bda5dSKevin Wolf p++; 1015ed7bda5dSKevin Wolf } 1016ed7bda5dSKevin Wolf if (*typestr == '?') { 1017ed7bda5dSKevin Wolf typestr++; 1018ed7bda5dSKevin Wolf if (*p == '\0') { 1019ed7bda5dSKevin Wolf /* no remaining string: NULL argument */ 1020ed7bda5dSKevin Wolf break; 1021ed7bda5dSKevin Wolf } 1022ed7bda5dSKevin Wolf } 1023ed7bda5dSKevin Wolf len = strlen(p); 1024ed7bda5dSKevin Wolf if (len <= 0) { 1025ed7bda5dSKevin Wolf monitor_printf(mon, "%s: string expected\n", 1026ed7bda5dSKevin Wolf cmd->name); 1027ed7bda5dSKevin Wolf goto fail; 1028ed7bda5dSKevin Wolf } 1029ed7bda5dSKevin Wolf qdict_put_str(qdict, key, p); 1030ed7bda5dSKevin Wolf p += len; 1031ed7bda5dSKevin Wolf } 1032ed7bda5dSKevin Wolf break; 1033ed7bda5dSKevin Wolf default: 1034ed7bda5dSKevin Wolf bad_type: 1035ed7bda5dSKevin Wolf monitor_printf(mon, "%s: unknown type '%c'\n", cmd->name, c); 1036ed7bda5dSKevin Wolf goto fail; 1037ed7bda5dSKevin Wolf } 1038ed7bda5dSKevin Wolf g_free(key); 1039ed7bda5dSKevin Wolf key = NULL; 1040ed7bda5dSKevin Wolf } 1041ed7bda5dSKevin Wolf /* check that all arguments were parsed */ 1042ed7bda5dSKevin Wolf while (qemu_isspace(*p)) { 1043ed7bda5dSKevin Wolf p++; 1044ed7bda5dSKevin Wolf } 1045ed7bda5dSKevin Wolf if (*p != '\0') { 1046ed7bda5dSKevin Wolf monitor_printf(mon, "%s: extraneous characters at the end of line\n", 1047ed7bda5dSKevin Wolf cmd->name); 1048ed7bda5dSKevin Wolf goto fail; 1049ed7bda5dSKevin Wolf } 1050ed7bda5dSKevin Wolf 1051ed7bda5dSKevin Wolf return qdict; 1052ed7bda5dSKevin Wolf 1053ed7bda5dSKevin Wolf fail: 1054ed7bda5dSKevin Wolf qobject_unref(qdict); 1055ed7bda5dSKevin Wolf g_free(key); 1056ed7bda5dSKevin Wolf return NULL; 1057ed7bda5dSKevin Wolf } 1058ed7bda5dSKevin Wolf 1059ed7bda5dSKevin Wolf void handle_hmp_command(MonitorHMP *mon, const char *cmdline) 1060ed7bda5dSKevin Wolf { 1061ed7bda5dSKevin Wolf QDict *qdict; 1062ed7bda5dSKevin Wolf const HMPCommand *cmd; 1063ed7bda5dSKevin Wolf const char *cmd_start = cmdline; 1064ed7bda5dSKevin Wolf 1065ed7bda5dSKevin Wolf trace_handle_hmp_command(mon, cmdline); 1066ed7bda5dSKevin Wolf 1067ed7bda5dSKevin Wolf cmd = monitor_parse_command(mon, cmdline, &cmdline, hmp_cmds); 1068ed7bda5dSKevin Wolf if (!cmd) { 1069ed7bda5dSKevin Wolf return; 1070ed7bda5dSKevin Wolf } 1071ed7bda5dSKevin Wolf 1072ed7bda5dSKevin Wolf qdict = monitor_parse_arguments(&mon->common, &cmdline, cmd); 1073ed7bda5dSKevin Wolf if (!qdict) { 1074ed7bda5dSKevin Wolf while (cmdline > cmd_start && qemu_isspace(cmdline[-1])) { 1075ed7bda5dSKevin Wolf cmdline--; 1076ed7bda5dSKevin Wolf } 1077ed7bda5dSKevin Wolf monitor_printf(&mon->common, "Try \"help %.*s\" for more information\n", 1078ed7bda5dSKevin Wolf (int)(cmdline - cmd_start), cmd_start); 1079ed7bda5dSKevin Wolf return; 1080ed7bda5dSKevin Wolf } 1081ed7bda5dSKevin Wolf 1082ed7bda5dSKevin Wolf cmd->cmd(&mon->common, qdict); 1083ed7bda5dSKevin Wolf qobject_unref(qdict); 1084ed7bda5dSKevin Wolf } 1085ed7bda5dSKevin Wolf 1086ed7bda5dSKevin Wolf static void cmd_completion(MonitorHMP *mon, const char *name, const char *list) 1087ed7bda5dSKevin Wolf { 1088ed7bda5dSKevin Wolf const char *p, *pstart; 1089ed7bda5dSKevin Wolf char cmd[128]; 1090ed7bda5dSKevin Wolf int len; 1091ed7bda5dSKevin Wolf 1092ed7bda5dSKevin Wolf p = list; 1093ed7bda5dSKevin Wolf for (;;) { 1094ed7bda5dSKevin Wolf pstart = p; 1095ed7bda5dSKevin Wolf p = qemu_strchrnul(p, '|'); 1096ed7bda5dSKevin Wolf len = p - pstart; 1097ed7bda5dSKevin Wolf if (len > sizeof(cmd) - 2) { 1098ed7bda5dSKevin Wolf len = sizeof(cmd) - 2; 1099ed7bda5dSKevin Wolf } 1100ed7bda5dSKevin Wolf memcpy(cmd, pstart, len); 1101ed7bda5dSKevin Wolf cmd[len] = '\0'; 1102ed7bda5dSKevin Wolf if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) { 1103ed7bda5dSKevin Wolf readline_add_completion(mon->rs, cmd); 1104ed7bda5dSKevin Wolf } 1105ed7bda5dSKevin Wolf if (*p == '\0') { 1106ed7bda5dSKevin Wolf break; 1107ed7bda5dSKevin Wolf } 1108ed7bda5dSKevin Wolf p++; 1109ed7bda5dSKevin Wolf } 1110ed7bda5dSKevin Wolf } 1111ed7bda5dSKevin Wolf 1112ed7bda5dSKevin Wolf static void file_completion(MonitorHMP *mon, const char *input) 1113ed7bda5dSKevin Wolf { 1114ed7bda5dSKevin Wolf DIR *ffs; 1115ed7bda5dSKevin Wolf struct dirent *d; 1116ed7bda5dSKevin Wolf char path[1024]; 1117ed7bda5dSKevin Wolf char file[1024], file_prefix[1024]; 1118ed7bda5dSKevin Wolf int input_path_len; 1119ed7bda5dSKevin Wolf const char *p; 1120ed7bda5dSKevin Wolf 1121ed7bda5dSKevin Wolf p = strrchr(input, '/'); 1122ed7bda5dSKevin Wolf if (!p) { 1123ed7bda5dSKevin Wolf input_path_len = 0; 1124ed7bda5dSKevin Wolf pstrcpy(file_prefix, sizeof(file_prefix), input); 1125ed7bda5dSKevin Wolf pstrcpy(path, sizeof(path), "."); 1126ed7bda5dSKevin Wolf } else { 1127ed7bda5dSKevin Wolf input_path_len = p - input + 1; 1128ed7bda5dSKevin Wolf memcpy(path, input, input_path_len); 1129ed7bda5dSKevin Wolf if (input_path_len > sizeof(path) - 1) { 1130ed7bda5dSKevin Wolf input_path_len = sizeof(path) - 1; 1131ed7bda5dSKevin Wolf } 1132ed7bda5dSKevin Wolf path[input_path_len] = '\0'; 1133ed7bda5dSKevin Wolf pstrcpy(file_prefix, sizeof(file_prefix), p + 1); 1134ed7bda5dSKevin Wolf } 1135ed7bda5dSKevin Wolf 1136ed7bda5dSKevin Wolf ffs = opendir(path); 1137ed7bda5dSKevin Wolf if (!ffs) { 1138ed7bda5dSKevin Wolf return; 1139ed7bda5dSKevin Wolf } 1140ed7bda5dSKevin Wolf for (;;) { 1141ed7bda5dSKevin Wolf struct stat sb; 1142ed7bda5dSKevin Wolf d = readdir(ffs); 1143ed7bda5dSKevin Wolf if (!d) { 1144ed7bda5dSKevin Wolf break; 1145ed7bda5dSKevin Wolf } 1146ed7bda5dSKevin Wolf 1147ed7bda5dSKevin Wolf if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) { 1148ed7bda5dSKevin Wolf continue; 1149ed7bda5dSKevin Wolf } 1150ed7bda5dSKevin Wolf 1151ed7bda5dSKevin Wolf if (strstart(d->d_name, file_prefix, NULL)) { 1152ed7bda5dSKevin Wolf memcpy(file, input, input_path_len); 1153ed7bda5dSKevin Wolf if (input_path_len < sizeof(file)) { 1154ed7bda5dSKevin Wolf pstrcpy(file + input_path_len, sizeof(file) - input_path_len, 1155ed7bda5dSKevin Wolf d->d_name); 1156ed7bda5dSKevin Wolf } 1157ed7bda5dSKevin Wolf /* 1158ed7bda5dSKevin Wolf * stat the file to find out if it's a directory. 1159ed7bda5dSKevin Wolf * In that case add a slash to speed up typing long paths 1160ed7bda5dSKevin Wolf */ 1161ed7bda5dSKevin Wolf if (stat(file, &sb) == 0 && S_ISDIR(sb.st_mode)) { 1162ed7bda5dSKevin Wolf pstrcat(file, sizeof(file), "/"); 1163ed7bda5dSKevin Wolf } 1164ed7bda5dSKevin Wolf readline_add_completion(mon->rs, file); 1165ed7bda5dSKevin Wolf } 1166ed7bda5dSKevin Wolf } 1167ed7bda5dSKevin Wolf closedir(ffs); 1168ed7bda5dSKevin Wolf } 1169ed7bda5dSKevin Wolf 1170ed7bda5dSKevin Wolf static const char *next_arg_type(const char *typestr) 1171ed7bda5dSKevin Wolf { 1172ed7bda5dSKevin Wolf const char *p = strchr(typestr, ':'); 1173ed7bda5dSKevin Wolf return (p != NULL ? ++p : typestr); 1174ed7bda5dSKevin Wolf } 1175ed7bda5dSKevin Wolf 1176ed7bda5dSKevin Wolf static void monitor_find_completion_by_table(MonitorHMP *mon, 1177ed7bda5dSKevin Wolf const HMPCommand *cmd_table, 1178ed7bda5dSKevin Wolf char **args, 1179ed7bda5dSKevin Wolf int nb_args) 1180ed7bda5dSKevin Wolf { 1181ed7bda5dSKevin Wolf const char *cmdname; 1182ed7bda5dSKevin Wolf int i; 1183ed7bda5dSKevin Wolf const char *ptype, *old_ptype, *str, *name; 1184ed7bda5dSKevin Wolf const HMPCommand *cmd; 1185ed7bda5dSKevin Wolf BlockBackend *blk = NULL; 1186ed7bda5dSKevin Wolf 1187ed7bda5dSKevin Wolf if (nb_args <= 1) { 1188ed7bda5dSKevin Wolf /* command completion */ 1189ed7bda5dSKevin Wolf if (nb_args == 0) { 1190ed7bda5dSKevin Wolf cmdname = ""; 1191ed7bda5dSKevin Wolf } else { 1192ed7bda5dSKevin Wolf cmdname = args[0]; 1193ed7bda5dSKevin Wolf } 1194ed7bda5dSKevin Wolf readline_set_completion_index(mon->rs, strlen(cmdname)); 1195ed7bda5dSKevin Wolf for (cmd = cmd_table; cmd->name != NULL; cmd++) { 1196ed7bda5dSKevin Wolf if (!runstate_check(RUN_STATE_PRECONFIG) || 1197ed7bda5dSKevin Wolf cmd_can_preconfig(cmd)) { 1198ed7bda5dSKevin Wolf cmd_completion(mon, cmdname, cmd->name); 1199ed7bda5dSKevin Wolf } 1200ed7bda5dSKevin Wolf } 1201ed7bda5dSKevin Wolf } else { 1202ed7bda5dSKevin Wolf /* find the command */ 1203ed7bda5dSKevin Wolf for (cmd = cmd_table; cmd->name != NULL; cmd++) { 1204ed7bda5dSKevin Wolf if (hmp_compare_cmd(args[0], cmd->name) && 1205ed7bda5dSKevin Wolf (!runstate_check(RUN_STATE_PRECONFIG) || 1206ed7bda5dSKevin Wolf cmd_can_preconfig(cmd))) { 1207ed7bda5dSKevin Wolf break; 1208ed7bda5dSKevin Wolf } 1209ed7bda5dSKevin Wolf } 1210ed7bda5dSKevin Wolf if (!cmd->name) { 1211ed7bda5dSKevin Wolf return; 1212ed7bda5dSKevin Wolf } 1213ed7bda5dSKevin Wolf 1214ed7bda5dSKevin Wolf if (cmd->sub_table) { 1215ed7bda5dSKevin Wolf /* do the job again */ 1216ed7bda5dSKevin Wolf monitor_find_completion_by_table(mon, cmd->sub_table, 1217ed7bda5dSKevin Wolf &args[1], nb_args - 1); 1218ed7bda5dSKevin Wolf return; 1219ed7bda5dSKevin Wolf } 1220ed7bda5dSKevin Wolf if (cmd->command_completion) { 1221ed7bda5dSKevin Wolf cmd->command_completion(mon->rs, nb_args, args[nb_args - 1]); 1222ed7bda5dSKevin Wolf return; 1223ed7bda5dSKevin Wolf } 1224ed7bda5dSKevin Wolf 1225ed7bda5dSKevin Wolf ptype = next_arg_type(cmd->args_type); 1226ed7bda5dSKevin Wolf for (i = 0; i < nb_args - 2; i++) { 1227ed7bda5dSKevin Wolf if (*ptype != '\0') { 1228ed7bda5dSKevin Wolf ptype = next_arg_type(ptype); 1229ed7bda5dSKevin Wolf while (*ptype == '?') { 1230ed7bda5dSKevin Wolf ptype = next_arg_type(ptype); 1231ed7bda5dSKevin Wolf } 1232ed7bda5dSKevin Wolf } 1233ed7bda5dSKevin Wolf } 1234ed7bda5dSKevin Wolf str = args[nb_args - 1]; 1235ed7bda5dSKevin Wolf old_ptype = NULL; 1236ed7bda5dSKevin Wolf while (*ptype == '-' && old_ptype != ptype) { 1237ed7bda5dSKevin Wolf old_ptype = ptype; 1238ed7bda5dSKevin Wolf ptype = next_arg_type(ptype); 1239ed7bda5dSKevin Wolf } 1240ed7bda5dSKevin Wolf switch (*ptype) { 1241ed7bda5dSKevin Wolf case 'F': 1242ed7bda5dSKevin Wolf /* file completion */ 1243ed7bda5dSKevin Wolf readline_set_completion_index(mon->rs, strlen(str)); 1244ed7bda5dSKevin Wolf file_completion(mon, str); 1245ed7bda5dSKevin Wolf break; 1246ed7bda5dSKevin Wolf case 'B': 1247ed7bda5dSKevin Wolf /* block device name completion */ 1248ed7bda5dSKevin Wolf readline_set_completion_index(mon->rs, strlen(str)); 1249ed7bda5dSKevin Wolf while ((blk = blk_next(blk)) != NULL) { 1250ed7bda5dSKevin Wolf name = blk_name(blk); 1251ed7bda5dSKevin Wolf if (str[0] == '\0' || 1252ed7bda5dSKevin Wolf !strncmp(name, str, strlen(str))) { 1253ed7bda5dSKevin Wolf readline_add_completion(mon->rs, name); 1254ed7bda5dSKevin Wolf } 1255ed7bda5dSKevin Wolf } 1256ed7bda5dSKevin Wolf break; 1257ed7bda5dSKevin Wolf case 's': 1258ed7bda5dSKevin Wolf case 'S': 1259ed7bda5dSKevin Wolf if (!strcmp(cmd->name, "help|?")) { 1260ed7bda5dSKevin Wolf monitor_find_completion_by_table(mon, cmd_table, 1261ed7bda5dSKevin Wolf &args[1], nb_args - 1); 1262ed7bda5dSKevin Wolf } 1263ed7bda5dSKevin Wolf break; 1264ed7bda5dSKevin Wolf default: 1265ed7bda5dSKevin Wolf break; 1266ed7bda5dSKevin Wolf } 1267ed7bda5dSKevin Wolf } 1268ed7bda5dSKevin Wolf } 1269ed7bda5dSKevin Wolf 1270ed7bda5dSKevin Wolf static void monitor_find_completion(void *opaque, 1271ed7bda5dSKevin Wolf const char *cmdline) 1272ed7bda5dSKevin Wolf { 1273ed7bda5dSKevin Wolf MonitorHMP *mon = opaque; 1274ed7bda5dSKevin Wolf char *args[MAX_ARGS]; 1275ed7bda5dSKevin Wolf int nb_args, len; 1276ed7bda5dSKevin Wolf 1277ed7bda5dSKevin Wolf /* 1. parse the cmdline */ 1278ed7bda5dSKevin Wolf if (parse_cmdline(cmdline, &nb_args, args) < 0) { 1279ed7bda5dSKevin Wolf return; 1280ed7bda5dSKevin Wolf } 1281ed7bda5dSKevin Wolf 1282ed7bda5dSKevin Wolf /* 1283ed7bda5dSKevin Wolf * if the line ends with a space, it means we want to complete the 1284ed7bda5dSKevin Wolf * next arg 1285ed7bda5dSKevin Wolf */ 1286ed7bda5dSKevin Wolf len = strlen(cmdline); 1287ed7bda5dSKevin Wolf if (len > 0 && qemu_isspace(cmdline[len - 1])) { 1288ed7bda5dSKevin Wolf if (nb_args >= MAX_ARGS) { 1289ed7bda5dSKevin Wolf goto cleanup; 1290ed7bda5dSKevin Wolf } 1291ed7bda5dSKevin Wolf args[nb_args++] = g_strdup(""); 1292ed7bda5dSKevin Wolf } 1293ed7bda5dSKevin Wolf 1294ed7bda5dSKevin Wolf /* 2. auto complete according to args */ 1295ed7bda5dSKevin Wolf monitor_find_completion_by_table(mon, hmp_cmds, args, nb_args); 1296ed7bda5dSKevin Wolf 1297ed7bda5dSKevin Wolf cleanup: 1298ed7bda5dSKevin Wolf free_cmdline_args(args, nb_args); 1299ed7bda5dSKevin Wolf } 1300ed7bda5dSKevin Wolf 1301ed7bda5dSKevin Wolf static void monitor_read(void *opaque, const uint8_t *buf, int size) 1302ed7bda5dSKevin Wolf { 1303*947e4744SKevin Wolf MonitorHMP *mon = container_of(opaque, MonitorHMP, common); 1304*947e4744SKevin Wolf Monitor *old_mon; 1305ed7bda5dSKevin Wolf int i; 1306ed7bda5dSKevin Wolf 1307*947e4744SKevin Wolf old_mon = monitor_set_cur(&mon->common); 1308ed7bda5dSKevin Wolf 1309ed7bda5dSKevin Wolf if (mon->rs) { 1310ed7bda5dSKevin Wolf for (i = 0; i < size; i++) { 1311ed7bda5dSKevin Wolf readline_handle_byte(mon->rs, buf[i]); 1312ed7bda5dSKevin Wolf } 1313ed7bda5dSKevin Wolf } else { 1314ed7bda5dSKevin Wolf if (size == 0 || buf[size - 1] != 0) { 1315*947e4744SKevin Wolf monitor_printf(&mon->common, "corrupted command\n"); 1316ed7bda5dSKevin Wolf } else { 1317ed7bda5dSKevin Wolf handle_hmp_command(mon, (char *)buf); 1318ed7bda5dSKevin Wolf } 1319ed7bda5dSKevin Wolf } 1320ed7bda5dSKevin Wolf 1321*947e4744SKevin Wolf monitor_set_cur(old_mon); 1322ed7bda5dSKevin Wolf } 1323ed7bda5dSKevin Wolf 1324083b266fSPhilippe Mathieu-Daudé static void monitor_event(void *opaque, QEMUChrEvent event) 1325ed7bda5dSKevin Wolf { 1326ed7bda5dSKevin Wolf Monitor *mon = opaque; 1327ed7bda5dSKevin Wolf MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common); 1328ed7bda5dSKevin Wolf 1329ed7bda5dSKevin Wolf switch (event) { 1330ed7bda5dSKevin Wolf case CHR_EVENT_MUX_IN: 1331ed7bda5dSKevin Wolf qemu_mutex_lock(&mon->mon_lock); 1332ed7bda5dSKevin Wolf mon->mux_out = 0; 1333ed7bda5dSKevin Wolf qemu_mutex_unlock(&mon->mon_lock); 1334ed7bda5dSKevin Wolf if (mon->reset_seen) { 1335ed7bda5dSKevin Wolf readline_restart(hmp_mon->rs); 1336ed7bda5dSKevin Wolf monitor_resume(mon); 1337ed7bda5dSKevin Wolf monitor_flush(mon); 1338ed7bda5dSKevin Wolf } else { 1339d73415a3SStefan Hajnoczi qatomic_mb_set(&mon->suspend_cnt, 0); 1340ed7bda5dSKevin Wolf } 1341ed7bda5dSKevin Wolf break; 1342ed7bda5dSKevin Wolf 1343ed7bda5dSKevin Wolf case CHR_EVENT_MUX_OUT: 1344ed7bda5dSKevin Wolf if (mon->reset_seen) { 1345d73415a3SStefan Hajnoczi if (qatomic_mb_read(&mon->suspend_cnt) == 0) { 1346ed7bda5dSKevin Wolf monitor_printf(mon, "\n"); 1347ed7bda5dSKevin Wolf } 1348ed7bda5dSKevin Wolf monitor_flush(mon); 1349ed7bda5dSKevin Wolf monitor_suspend(mon); 1350ed7bda5dSKevin Wolf } else { 1351d73415a3SStefan Hajnoczi qatomic_inc(&mon->suspend_cnt); 1352ed7bda5dSKevin Wolf } 1353ed7bda5dSKevin Wolf qemu_mutex_lock(&mon->mon_lock); 1354ed7bda5dSKevin Wolf mon->mux_out = 1; 1355ed7bda5dSKevin Wolf qemu_mutex_unlock(&mon->mon_lock); 1356ed7bda5dSKevin Wolf break; 1357ed7bda5dSKevin Wolf 1358ed7bda5dSKevin Wolf case CHR_EVENT_OPENED: 1359ed7bda5dSKevin Wolf monitor_printf(mon, "QEMU %s monitor - type 'help' for more " 1360ed7bda5dSKevin Wolf "information\n", QEMU_VERSION); 1361ed7bda5dSKevin Wolf if (!mon->mux_out) { 1362ed7bda5dSKevin Wolf readline_restart(hmp_mon->rs); 1363ed7bda5dSKevin Wolf readline_show_prompt(hmp_mon->rs); 1364ed7bda5dSKevin Wolf } 1365ed7bda5dSKevin Wolf mon->reset_seen = 1; 1366ed7bda5dSKevin Wolf mon_refcount++; 1367ed7bda5dSKevin Wolf break; 1368ed7bda5dSKevin Wolf 1369ed7bda5dSKevin Wolf case CHR_EVENT_CLOSED: 1370ed7bda5dSKevin Wolf mon_refcount--; 1371ed7bda5dSKevin Wolf monitor_fdsets_cleanup(); 1372ed7bda5dSKevin Wolf break; 13734904ca6aSPhilippe Mathieu-Daudé 13744904ca6aSPhilippe Mathieu-Daudé case CHR_EVENT_BREAK: 13754904ca6aSPhilippe Mathieu-Daudé /* Ignored */ 13764904ca6aSPhilippe Mathieu-Daudé break; 1377ed7bda5dSKevin Wolf } 1378ed7bda5dSKevin Wolf } 1379ed7bda5dSKevin Wolf 1380ed7bda5dSKevin Wolf 1381ed7bda5dSKevin Wolf /* 1382ed7bda5dSKevin Wolf * These functions just adapt the readline interface in a typesafe way. We 1383ed7bda5dSKevin Wolf * could cast function pointers but that discards compiler checks. 1384ed7bda5dSKevin Wolf */ 1385ed7bda5dSKevin Wolf static void GCC_FMT_ATTR(2, 3) monitor_readline_printf(void *opaque, 1386ed7bda5dSKevin Wolf const char *fmt, ...) 1387ed7bda5dSKevin Wolf { 1388ed7bda5dSKevin Wolf MonitorHMP *mon = opaque; 1389ed7bda5dSKevin Wolf va_list ap; 1390ed7bda5dSKevin Wolf va_start(ap, fmt); 1391ed7bda5dSKevin Wolf monitor_vprintf(&mon->common, fmt, ap); 1392ed7bda5dSKevin Wolf va_end(ap); 1393ed7bda5dSKevin Wolf } 1394ed7bda5dSKevin Wolf 1395ed7bda5dSKevin Wolf static void monitor_readline_flush(void *opaque) 1396ed7bda5dSKevin Wolf { 1397ed7bda5dSKevin Wolf MonitorHMP *mon = opaque; 1398ed7bda5dSKevin Wolf monitor_flush(&mon->common); 1399ed7bda5dSKevin Wolf } 1400ed7bda5dSKevin Wolf 14018e9119a8SKevin Wolf void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp) 1402ed7bda5dSKevin Wolf { 1403ed7bda5dSKevin Wolf MonitorHMP *mon = g_new0(MonitorHMP, 1); 1404ed7bda5dSKevin Wolf 14058e9119a8SKevin Wolf if (!qemu_chr_fe_init(&mon->common.chr, chr, errp)) { 14068e9119a8SKevin Wolf g_free(mon); 14078e9119a8SKevin Wolf return; 14088e9119a8SKevin Wolf } 14098e9119a8SKevin Wolf 141092082416SKevin Wolf monitor_data_init(&mon->common, false, false, false); 1411ed7bda5dSKevin Wolf 1412fbfc29e3SKevin Wolf mon->use_readline = use_readline; 141392082416SKevin Wolf if (mon->use_readline) { 1414ed7bda5dSKevin Wolf mon->rs = readline_init(monitor_readline_printf, 1415ed7bda5dSKevin Wolf monitor_readline_flush, 1416ed7bda5dSKevin Wolf mon, 1417ed7bda5dSKevin Wolf monitor_find_completion); 1418ed7bda5dSKevin Wolf monitor_read_command(mon, 0); 1419ed7bda5dSKevin Wolf } 1420ed7bda5dSKevin Wolf 1421ed7bda5dSKevin Wolf qemu_chr_fe_set_handlers(&mon->common.chr, monitor_can_read, monitor_read, 1422ed7bda5dSKevin Wolf monitor_event, NULL, &mon->common, NULL, true); 1423ed7bda5dSKevin Wolf monitor_list_append(&mon->common); 1424ed7bda5dSKevin Wolf } 1425