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