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>
27164dafd1SPaolo Bonzini #include "hw/qdev-core.h"
28ed7bda5dSKevin Wolf #include "monitor-internal.h"
29f9429c67SDaniel P. Berrangé #include "monitor/hmp.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"
39ed7bda5dSKevin Wolf #include "trace.h"
40ed7bda5dSKevin Wolf
monitor_command_cb(void * opaque,const char * cmdline,void * readline_opaque)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
monitor_read_command(MonitorHMP * mon,int show_prompt)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
monitor_read_password(MonitorHMP * mon,ReadLineFunc * readline_func,void * opaque)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
get_str(char * buf,int buf_size,const char ** pp)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
free_cmdline_args(char ** args,int nb_args)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 */
parse_cmdline(const char * cmdline,int * pnb_args,char ** args)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 */
cmd_can_preconfig(const HMPCommand * cmd)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
cmd_available(const HMPCommand * cmd)2164cd29274SPaolo Bonzini static bool cmd_available(const HMPCommand *cmd)
2174cd29274SPaolo Bonzini {
2182f181fbdSPaolo Bonzini return phase_check(PHASE_MACHINE_READY) || cmd_can_preconfig(cmd);
2194cd29274SPaolo Bonzini }
2204cd29274SPaolo Bonzini
help_cmd_dump_one(Monitor * mon,const HMPCommand * cmd,char ** prefix_args,int prefix_args_nb)221ed7bda5dSKevin Wolf static void help_cmd_dump_one(Monitor *mon,
222ed7bda5dSKevin Wolf const HMPCommand *cmd,
223ed7bda5dSKevin Wolf char **prefix_args,
224ed7bda5dSKevin Wolf int prefix_args_nb)
225ed7bda5dSKevin Wolf {
226ed7bda5dSKevin Wolf int i;
227ed7bda5dSKevin Wolf
2284cd29274SPaolo Bonzini if (!cmd_available(cmd)) {
229ed7bda5dSKevin Wolf return;
230ed7bda5dSKevin Wolf }
231ed7bda5dSKevin Wolf
232ed7bda5dSKevin Wolf for (i = 0; i < prefix_args_nb; i++) {
233ed7bda5dSKevin Wolf monitor_printf(mon, "%s ", prefix_args[i]);
234ed7bda5dSKevin Wolf }
235ed7bda5dSKevin Wolf monitor_printf(mon, "%s %s -- %s\n", cmd->name, cmd->params, cmd->help);
236ed7bda5dSKevin Wolf }
237ed7bda5dSKevin Wolf
238ed7bda5dSKevin Wolf /* @args[@arg_index] is the valid command need to find in @cmds */
help_cmd_dump(Monitor * mon,const HMPCommand * cmds,char ** args,int nb_args,int arg_index)239ed7bda5dSKevin Wolf static void help_cmd_dump(Monitor *mon, const HMPCommand *cmds,
240ed7bda5dSKevin Wolf char **args, int nb_args, int arg_index)
241ed7bda5dSKevin Wolf {
242ed7bda5dSKevin Wolf const HMPCommand *cmd;
243ed7bda5dSKevin Wolf size_t i;
244ed7bda5dSKevin Wolf
245ed7bda5dSKevin Wolf /* No valid arg need to compare with, dump all in *cmds */
246ed7bda5dSKevin Wolf if (arg_index >= nb_args) {
247ed7bda5dSKevin Wolf for (cmd = cmds; cmd->name != NULL; cmd++) {
248ed7bda5dSKevin Wolf help_cmd_dump_one(mon, cmd, args, arg_index);
249ed7bda5dSKevin Wolf }
250ed7bda5dSKevin Wolf return;
251ed7bda5dSKevin Wolf }
252ed7bda5dSKevin Wolf
253ed7bda5dSKevin Wolf /* Find one entry to dump */
254ed7bda5dSKevin Wolf for (cmd = cmds; cmd->name != NULL; cmd++) {
255ed7bda5dSKevin Wolf if (hmp_compare_cmd(args[arg_index], cmd->name) &&
2564cd29274SPaolo Bonzini cmd_available(cmd)) {
257ed7bda5dSKevin Wolf if (cmd->sub_table) {
258ed7bda5dSKevin Wolf /* continue with next arg */
259ed7bda5dSKevin Wolf help_cmd_dump(mon, cmd->sub_table,
260ed7bda5dSKevin Wolf args, nb_args, arg_index + 1);
261ed7bda5dSKevin Wolf } else {
262ed7bda5dSKevin Wolf help_cmd_dump_one(mon, cmd, args, arg_index);
263ed7bda5dSKevin Wolf }
264ed7bda5dSKevin Wolf return;
265ed7bda5dSKevin Wolf }
266ed7bda5dSKevin Wolf }
267ed7bda5dSKevin Wolf
268ed7bda5dSKevin Wolf /* Command not found */
269ed7bda5dSKevin Wolf monitor_printf(mon, "unknown command: '");
270ed7bda5dSKevin Wolf for (i = 0; i <= arg_index; i++) {
271ed7bda5dSKevin Wolf monitor_printf(mon, "%s%s", args[i], i == arg_index ? "'\n" : " ");
272ed7bda5dSKevin Wolf }
273ed7bda5dSKevin Wolf }
274ed7bda5dSKevin Wolf
hmp_help_cmd(Monitor * mon,const char * name)2755ec92f2dSMarkus Armbruster void hmp_help_cmd(Monitor *mon, const char *name)
276ed7bda5dSKevin Wolf {
277ed7bda5dSKevin Wolf char *args[MAX_ARGS];
278ed7bda5dSKevin Wolf int nb_args = 0;
279ed7bda5dSKevin Wolf
280ed7bda5dSKevin Wolf /* 1. parse user input */
281ed7bda5dSKevin Wolf if (name) {
282ed7bda5dSKevin Wolf /* special case for log, directly dump and return */
283ed7bda5dSKevin Wolf if (!strcmp(name, "log")) {
284ed7bda5dSKevin Wolf const QEMULogItem *item;
285ed7bda5dSKevin Wolf monitor_printf(mon, "Log items (comma separated):\n");
2863183bb3fSDongli Zhang monitor_printf(mon, "%-15s %s\n", "none", "remove all logs");
287ed7bda5dSKevin Wolf for (item = qemu_log_items; item->mask != 0; item++) {
2883183bb3fSDongli Zhang monitor_printf(mon, "%-15s %s\n", item->name, item->help);
289ed7bda5dSKevin Wolf }
2903183bb3fSDongli Zhang #ifdef CONFIG_TRACE_LOG
2913183bb3fSDongli Zhang monitor_printf(mon, "trace:PATTERN enable trace events\n");
2923183bb3fSDongli Zhang monitor_printf(mon, "\nUse \"log trace:help\" to get a list of "
2933183bb3fSDongli Zhang "trace events.\n\n");
2943183bb3fSDongli Zhang #endif
295ed7bda5dSKevin Wolf return;
296ed7bda5dSKevin Wolf }
297ed7bda5dSKevin Wolf
298ed7bda5dSKevin Wolf if (parse_cmdline(name, &nb_args, args) < 0) {
299ed7bda5dSKevin Wolf return;
300ed7bda5dSKevin Wolf }
301ed7bda5dSKevin Wolf }
302ed7bda5dSKevin Wolf
303ed7bda5dSKevin Wolf /* 2. dump the contents according to parsed args */
304ed7bda5dSKevin Wolf help_cmd_dump(mon, hmp_cmds, args, nb_args, 0);
305ed7bda5dSKevin Wolf
306ed7bda5dSKevin Wolf free_cmdline_args(args, nb_args);
307ed7bda5dSKevin Wolf }
308ed7bda5dSKevin Wolf
309ed7bda5dSKevin Wolf /*******************************************************************/
310ed7bda5dSKevin Wolf
311ed7bda5dSKevin Wolf static const char *pch;
312ed7bda5dSKevin Wolf static sigjmp_buf expr_env;
313ed7bda5dSKevin Wolf
3148905770bSMarc-André Lureau static G_NORETURN G_GNUC_PRINTF(2, 3)
expr_error(Monitor * mon,const char * fmt,...)3158905770bSMarc-André Lureau void expr_error(Monitor *mon, const char *fmt, ...)
316ed7bda5dSKevin Wolf {
317ed7bda5dSKevin Wolf va_list ap;
318ed7bda5dSKevin Wolf va_start(ap, fmt);
319ed7bda5dSKevin Wolf monitor_vprintf(mon, fmt, ap);
320ed7bda5dSKevin Wolf monitor_printf(mon, "\n");
321ed7bda5dSKevin Wolf va_end(ap);
322ed7bda5dSKevin Wolf siglongjmp(expr_env, 1);
323ed7bda5dSKevin Wolf }
324ed7bda5dSKevin Wolf
next(void)325ed7bda5dSKevin Wolf static void next(void)
326ed7bda5dSKevin Wolf {
327ed7bda5dSKevin Wolf if (*pch != '\0') {
328ed7bda5dSKevin Wolf pch++;
329ed7bda5dSKevin Wolf while (qemu_isspace(*pch)) {
330ed7bda5dSKevin Wolf pch++;
331ed7bda5dSKevin Wolf }
332ed7bda5dSKevin Wolf }
333ed7bda5dSKevin Wolf }
334ed7bda5dSKevin Wolf
335ed7bda5dSKevin Wolf static int64_t expr_sum(Monitor *mon);
336ed7bda5dSKevin Wolf
expr_unary(Monitor * mon)337ed7bda5dSKevin Wolf static int64_t expr_unary(Monitor *mon)
338ed7bda5dSKevin Wolf {
339ed7bda5dSKevin Wolf int64_t n;
340ed7bda5dSKevin Wolf char *p;
341ed7bda5dSKevin Wolf int ret;
342ed7bda5dSKevin Wolf
343ed7bda5dSKevin Wolf switch (*pch) {
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_unary(mon);
355ed7bda5dSKevin Wolf break;
356ed7bda5dSKevin Wolf case '(':
357ed7bda5dSKevin Wolf next();
358ed7bda5dSKevin Wolf n = expr_sum(mon);
359ed7bda5dSKevin Wolf if (*pch != ')') {
360ed7bda5dSKevin Wolf expr_error(mon, "')' expected");
361ed7bda5dSKevin Wolf }
362ed7bda5dSKevin Wolf next();
363ed7bda5dSKevin Wolf break;
364ed7bda5dSKevin Wolf case '\'':
365ed7bda5dSKevin Wolf pch++;
366ed7bda5dSKevin Wolf if (*pch == '\0') {
367ed7bda5dSKevin Wolf expr_error(mon, "character constant expected");
368ed7bda5dSKevin Wolf }
369ed7bda5dSKevin Wolf n = *pch;
370ed7bda5dSKevin Wolf pch++;
371ed7bda5dSKevin Wolf if (*pch != '\'') {
372ed7bda5dSKevin Wolf expr_error(mon, "missing terminating \' character");
373ed7bda5dSKevin Wolf }
374ed7bda5dSKevin Wolf next();
375ed7bda5dSKevin Wolf break;
376ed7bda5dSKevin Wolf case '$':
377ed7bda5dSKevin Wolf {
378ed7bda5dSKevin Wolf char buf[128], *q;
379ed7bda5dSKevin Wolf int64_t reg = 0;
380ed7bda5dSKevin Wolf
381ed7bda5dSKevin Wolf pch++;
382ed7bda5dSKevin Wolf q = buf;
383ed7bda5dSKevin Wolf while ((*pch >= 'a' && *pch <= 'z') ||
384ed7bda5dSKevin Wolf (*pch >= 'A' && *pch <= 'Z') ||
385ed7bda5dSKevin Wolf (*pch >= '0' && *pch <= '9') ||
386ed7bda5dSKevin Wolf *pch == '_' || *pch == '.') {
387ed7bda5dSKevin Wolf if ((q - buf) < sizeof(buf) - 1) {
388ed7bda5dSKevin Wolf *q++ = *pch;
389ed7bda5dSKevin Wolf }
390ed7bda5dSKevin Wolf pch++;
391ed7bda5dSKevin Wolf }
392ed7bda5dSKevin Wolf while (qemu_isspace(*pch)) {
393ed7bda5dSKevin Wolf pch++;
394ed7bda5dSKevin Wolf }
395ed7bda5dSKevin Wolf *q = 0;
3962fc5d01bSKevin Wolf ret = get_monitor_def(mon, ®, buf);
397ed7bda5dSKevin Wolf if (ret < 0) {
398ed7bda5dSKevin Wolf expr_error(mon, "unknown register");
399ed7bda5dSKevin Wolf }
400ed7bda5dSKevin Wolf n = reg;
401ed7bda5dSKevin Wolf }
402ed7bda5dSKevin Wolf break;
403ed7bda5dSKevin Wolf case '\0':
404ed7bda5dSKevin Wolf expr_error(mon, "unexpected end of expression");
405ed7bda5dSKevin Wolf n = 0;
406ed7bda5dSKevin Wolf break;
407ed7bda5dSKevin Wolf default:
408ed7bda5dSKevin Wolf errno = 0;
409ed7bda5dSKevin Wolf n = strtoull(pch, &p, 0);
410ed7bda5dSKevin Wolf if (errno == ERANGE) {
411ed7bda5dSKevin Wolf expr_error(mon, "number too large");
412ed7bda5dSKevin Wolf }
413ed7bda5dSKevin Wolf if (pch == p) {
414ed7bda5dSKevin Wolf expr_error(mon, "invalid char '%c' in expression", *p);
415ed7bda5dSKevin Wolf }
416ed7bda5dSKevin Wolf pch = p;
417ed7bda5dSKevin Wolf while (qemu_isspace(*pch)) {
418ed7bda5dSKevin Wolf pch++;
419ed7bda5dSKevin Wolf }
420ed7bda5dSKevin Wolf break;
421ed7bda5dSKevin Wolf }
422ed7bda5dSKevin Wolf return n;
423ed7bda5dSKevin Wolf }
424ed7bda5dSKevin Wolf
expr_prod(Monitor * mon)425ed7bda5dSKevin Wolf static int64_t expr_prod(Monitor *mon)
426ed7bda5dSKevin Wolf {
427ed7bda5dSKevin Wolf int64_t val, val2;
428ed7bda5dSKevin Wolf int op;
429ed7bda5dSKevin Wolf
430ed7bda5dSKevin Wolf val = expr_unary(mon);
431ed7bda5dSKevin Wolf for (;;) {
432ed7bda5dSKevin Wolf op = *pch;
433ed7bda5dSKevin Wolf if (op != '*' && op != '/' && op != '%') {
434ed7bda5dSKevin Wolf break;
435ed7bda5dSKevin Wolf }
436ed7bda5dSKevin Wolf next();
437ed7bda5dSKevin Wolf val2 = expr_unary(mon);
438ed7bda5dSKevin Wolf switch (op) {
439ed7bda5dSKevin Wolf default:
440ed7bda5dSKevin Wolf case '*':
441ed7bda5dSKevin Wolf val *= val2;
442ed7bda5dSKevin Wolf break;
443ed7bda5dSKevin Wolf case '/':
444ed7bda5dSKevin Wolf case '%':
445ed7bda5dSKevin Wolf if (val2 == 0) {
446ed7bda5dSKevin Wolf expr_error(mon, "division by zero");
447ed7bda5dSKevin Wolf }
448ed7bda5dSKevin Wolf if (op == '/') {
449ed7bda5dSKevin Wolf val /= val2;
450ed7bda5dSKevin Wolf } else {
451ed7bda5dSKevin Wolf val %= val2;
452ed7bda5dSKevin Wolf }
453ed7bda5dSKevin Wolf break;
454ed7bda5dSKevin Wolf }
455ed7bda5dSKevin Wolf }
456ed7bda5dSKevin Wolf return val;
457ed7bda5dSKevin Wolf }
458ed7bda5dSKevin Wolf
expr_logic(Monitor * mon)459ed7bda5dSKevin Wolf static int64_t expr_logic(Monitor *mon)
460ed7bda5dSKevin Wolf {
461ed7bda5dSKevin Wolf int64_t val, val2;
462ed7bda5dSKevin Wolf int op;
463ed7bda5dSKevin Wolf
464ed7bda5dSKevin Wolf val = expr_prod(mon);
465ed7bda5dSKevin Wolf for (;;) {
466ed7bda5dSKevin Wolf op = *pch;
467ed7bda5dSKevin Wolf if (op != '&' && op != '|' && op != '^') {
468ed7bda5dSKevin Wolf break;
469ed7bda5dSKevin Wolf }
470ed7bda5dSKevin Wolf next();
471ed7bda5dSKevin Wolf val2 = expr_prod(mon);
472ed7bda5dSKevin Wolf switch (op) {
473ed7bda5dSKevin Wolf default:
474ed7bda5dSKevin Wolf case '&':
475ed7bda5dSKevin Wolf val &= val2;
476ed7bda5dSKevin Wolf break;
477ed7bda5dSKevin Wolf case '|':
478ed7bda5dSKevin Wolf val |= val2;
479ed7bda5dSKevin Wolf break;
480ed7bda5dSKevin Wolf case '^':
481ed7bda5dSKevin Wolf val ^= val2;
482ed7bda5dSKevin Wolf break;
483ed7bda5dSKevin Wolf }
484ed7bda5dSKevin Wolf }
485ed7bda5dSKevin Wolf return val;
486ed7bda5dSKevin Wolf }
487ed7bda5dSKevin Wolf
expr_sum(Monitor * mon)488ed7bda5dSKevin Wolf static int64_t expr_sum(Monitor *mon)
489ed7bda5dSKevin Wolf {
490ed7bda5dSKevin Wolf int64_t val, val2;
491ed7bda5dSKevin Wolf int op;
492ed7bda5dSKevin Wolf
493ed7bda5dSKevin Wolf val = expr_logic(mon);
494ed7bda5dSKevin Wolf for (;;) {
495ed7bda5dSKevin Wolf op = *pch;
496ed7bda5dSKevin Wolf if (op != '+' && op != '-') {
497ed7bda5dSKevin Wolf break;
498ed7bda5dSKevin Wolf }
499ed7bda5dSKevin Wolf next();
500ed7bda5dSKevin Wolf val2 = expr_logic(mon);
501ed7bda5dSKevin Wolf if (op == '+') {
502ed7bda5dSKevin Wolf val += val2;
503ed7bda5dSKevin Wolf } else {
504ed7bda5dSKevin Wolf val -= val2;
505ed7bda5dSKevin Wolf }
506ed7bda5dSKevin Wolf }
507ed7bda5dSKevin Wolf return val;
508ed7bda5dSKevin Wolf }
509ed7bda5dSKevin Wolf
get_expr(Monitor * mon,int64_t * pval,const char ** pp)510ed7bda5dSKevin Wolf static int get_expr(Monitor *mon, int64_t *pval, const char **pp)
511ed7bda5dSKevin Wolf {
512ed7bda5dSKevin Wolf pch = *pp;
513ed7bda5dSKevin Wolf if (sigsetjmp(expr_env, 0)) {
514ed7bda5dSKevin Wolf *pp = pch;
515ed7bda5dSKevin Wolf return -1;
516ed7bda5dSKevin Wolf }
517ed7bda5dSKevin Wolf while (qemu_isspace(*pch)) {
518ed7bda5dSKevin Wolf pch++;
519ed7bda5dSKevin Wolf }
520ed7bda5dSKevin Wolf *pval = expr_sum(mon);
521ed7bda5dSKevin Wolf *pp = pch;
522ed7bda5dSKevin Wolf return 0;
523ed7bda5dSKevin Wolf }
524ed7bda5dSKevin Wolf
get_double(Monitor * mon,double * pval,const char ** pp)525ed7bda5dSKevin Wolf static int get_double(Monitor *mon, double *pval, const char **pp)
526ed7bda5dSKevin Wolf {
527ed7bda5dSKevin Wolf const char *p = *pp;
528ed7bda5dSKevin Wolf char *tailp;
529ed7bda5dSKevin Wolf double d;
530ed7bda5dSKevin Wolf
531ed7bda5dSKevin Wolf d = strtod(p, &tailp);
532ed7bda5dSKevin Wolf if (tailp == p) {
533ed7bda5dSKevin Wolf monitor_printf(mon, "Number expected\n");
534ed7bda5dSKevin Wolf return -1;
535ed7bda5dSKevin Wolf }
536ed7bda5dSKevin Wolf if (d != d || d - d != 0) {
537ed7bda5dSKevin Wolf /* NaN or infinity */
538ed7bda5dSKevin Wolf monitor_printf(mon, "Bad number\n");
539ed7bda5dSKevin Wolf return -1;
540ed7bda5dSKevin Wolf }
541ed7bda5dSKevin Wolf *pval = d;
542ed7bda5dSKevin Wolf *pp = tailp;
543ed7bda5dSKevin Wolf return 0;
544ed7bda5dSKevin Wolf }
545ed7bda5dSKevin Wolf
546ed7bda5dSKevin Wolf /*
547ed7bda5dSKevin Wolf * Store the command-name in cmdname, and return a pointer to
548ed7bda5dSKevin Wolf * the remaining of the command string.
549ed7bda5dSKevin Wolf */
get_command_name(const char * cmdline,char * cmdname,size_t nlen)550ed7bda5dSKevin Wolf static const char *get_command_name(const char *cmdline,
551ed7bda5dSKevin Wolf char *cmdname, size_t nlen)
552ed7bda5dSKevin Wolf {
553ed7bda5dSKevin Wolf size_t len;
554ed7bda5dSKevin Wolf const char *p, *pstart;
555ed7bda5dSKevin Wolf
556ed7bda5dSKevin Wolf p = cmdline;
557ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
558ed7bda5dSKevin Wolf p++;
559ed7bda5dSKevin Wolf }
560ed7bda5dSKevin Wolf if (*p == '\0') {
561ed7bda5dSKevin Wolf return NULL;
562ed7bda5dSKevin Wolf }
563ed7bda5dSKevin Wolf pstart = p;
564ed7bda5dSKevin Wolf while (*p != '\0' && *p != '/' && !qemu_isspace(*p)) {
565ed7bda5dSKevin Wolf p++;
566ed7bda5dSKevin Wolf }
567ed7bda5dSKevin Wolf len = p - pstart;
568ed7bda5dSKevin Wolf if (len > nlen - 1) {
569ed7bda5dSKevin Wolf len = nlen - 1;
570ed7bda5dSKevin Wolf }
571ed7bda5dSKevin Wolf memcpy(cmdname, pstart, len);
572ed7bda5dSKevin Wolf cmdname[len] = '\0';
573ed7bda5dSKevin Wolf return p;
574ed7bda5dSKevin Wolf }
575ed7bda5dSKevin Wolf
576ed7bda5dSKevin Wolf /**
577ed7bda5dSKevin Wolf * Read key of 'type' into 'key' and return the current
578ed7bda5dSKevin Wolf * 'type' pointer.
579ed7bda5dSKevin Wolf */
key_get_info(const char * type,char ** key)580ed7bda5dSKevin Wolf static char *key_get_info(const char *type, char **key)
581ed7bda5dSKevin Wolf {
582ed7bda5dSKevin Wolf size_t len;
583ed7bda5dSKevin Wolf char *p, *str;
584ed7bda5dSKevin Wolf
585ed7bda5dSKevin Wolf if (*type == ',') {
586ed7bda5dSKevin Wolf type++;
587ed7bda5dSKevin Wolf }
588ed7bda5dSKevin Wolf
589ed7bda5dSKevin Wolf p = strchr(type, ':');
590ed7bda5dSKevin Wolf if (!p) {
591ed7bda5dSKevin Wolf *key = NULL;
592ed7bda5dSKevin Wolf return NULL;
593ed7bda5dSKevin Wolf }
594ed7bda5dSKevin Wolf len = p - type;
595ed7bda5dSKevin Wolf
596ed7bda5dSKevin Wolf str = g_malloc(len + 1);
597ed7bda5dSKevin Wolf memcpy(str, type, len);
598ed7bda5dSKevin Wolf str[len] = '\0';
599ed7bda5dSKevin Wolf
600ed7bda5dSKevin Wolf *key = str;
601ed7bda5dSKevin Wolf return ++p;
602ed7bda5dSKevin Wolf }
603ed7bda5dSKevin Wolf
604ed7bda5dSKevin Wolf static int default_fmt_format = 'x';
605ed7bda5dSKevin Wolf static int default_fmt_size = 4;
606ed7bda5dSKevin Wolf
is_valid_option(const char * c,const char * typestr)607ed7bda5dSKevin Wolf static int is_valid_option(const char *c, const char *typestr)
608ed7bda5dSKevin Wolf {
609ed7bda5dSKevin Wolf char option[3];
610ed7bda5dSKevin Wolf
611ed7bda5dSKevin Wolf option[0] = '-';
612ed7bda5dSKevin Wolf option[1] = *c;
613ed7bda5dSKevin Wolf option[2] = '\0';
614ed7bda5dSKevin Wolf
615ed7bda5dSKevin Wolf typestr = strstr(typestr, option);
616ed7bda5dSKevin Wolf return (typestr != NULL);
617ed7bda5dSKevin Wolf }
618ed7bda5dSKevin Wolf
search_dispatch_table(const HMPCommand * disp_table,const char * cmdname)619ed7bda5dSKevin Wolf static const HMPCommand *search_dispatch_table(const HMPCommand *disp_table,
620ed7bda5dSKevin Wolf const char *cmdname)
621ed7bda5dSKevin Wolf {
622ed7bda5dSKevin Wolf const HMPCommand *cmd;
623ed7bda5dSKevin Wolf
624ed7bda5dSKevin Wolf for (cmd = disp_table; cmd->name != NULL; cmd++) {
625ed7bda5dSKevin Wolf if (hmp_compare_cmd(cmdname, cmd->name)) {
626ed7bda5dSKevin Wolf return cmd;
627ed7bda5dSKevin Wolf }
628ed7bda5dSKevin Wolf }
629ed7bda5dSKevin Wolf
630ed7bda5dSKevin Wolf return NULL;
631ed7bda5dSKevin Wolf }
632ed7bda5dSKevin Wolf
633ed7bda5dSKevin Wolf /*
634ed7bda5dSKevin Wolf * Parse command name from @cmdp according to command table @table.
635ed7bda5dSKevin Wolf * If blank, return NULL.
636ed7bda5dSKevin Wolf * Else, if no valid command can be found, report to @mon, and return
637ed7bda5dSKevin Wolf * NULL.
638ed7bda5dSKevin Wolf * Else, change @cmdp to point right behind the name, and return its
639ed7bda5dSKevin Wolf * command table entry.
640ed7bda5dSKevin Wolf * Do not assume the return value points into @table! It doesn't when
641ed7bda5dSKevin Wolf * the command is found in a sub-command table.
642ed7bda5dSKevin Wolf */
monitor_parse_command(MonitorHMP * hmp_mon,const char * cmdp_start,const char ** cmdp,HMPCommand * table)643ed7bda5dSKevin Wolf static const HMPCommand *monitor_parse_command(MonitorHMP *hmp_mon,
644ed7bda5dSKevin Wolf const char *cmdp_start,
645ed7bda5dSKevin Wolf const char **cmdp,
646ed7bda5dSKevin Wolf HMPCommand *table)
647ed7bda5dSKevin Wolf {
648ed7bda5dSKevin Wolf Monitor *mon = &hmp_mon->common;
649ed7bda5dSKevin Wolf const char *p;
650ed7bda5dSKevin Wolf const HMPCommand *cmd;
651ed7bda5dSKevin Wolf char cmdname[256];
652ed7bda5dSKevin Wolf
653ed7bda5dSKevin Wolf /* extract the command name */
654ed7bda5dSKevin Wolf p = get_command_name(*cmdp, cmdname, sizeof(cmdname));
655ed7bda5dSKevin Wolf if (!p) {
656ed7bda5dSKevin Wolf return NULL;
657ed7bda5dSKevin Wolf }
658ed7bda5dSKevin Wolf
659ed7bda5dSKevin Wolf cmd = search_dispatch_table(table, cmdname);
660ed7bda5dSKevin Wolf if (!cmd) {
661ed7bda5dSKevin Wolf monitor_printf(mon, "unknown command: '%.*s'\n",
662ed7bda5dSKevin Wolf (int)(p - cmdp_start), cmdp_start);
663ed7bda5dSKevin Wolf return NULL;
664ed7bda5dSKevin Wolf }
6654cd29274SPaolo Bonzini if (!cmd_available(cmd)) {
666164dafd1SPaolo Bonzini monitor_printf(mon, "Command '%.*s' not available "
667164dafd1SPaolo Bonzini "until machine initialization has completed.\n",
668ed7bda5dSKevin Wolf (int)(p - cmdp_start), cmdp_start);
669ed7bda5dSKevin Wolf return NULL;
670ed7bda5dSKevin Wolf }
671ed7bda5dSKevin Wolf
672ed7bda5dSKevin Wolf /* filter out following useless space */
673ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
674ed7bda5dSKevin Wolf p++;
675ed7bda5dSKevin Wolf }
676ed7bda5dSKevin Wolf
677ed7bda5dSKevin Wolf *cmdp = p;
678ed7bda5dSKevin Wolf /* search sub command */
679ed7bda5dSKevin Wolf if (cmd->sub_table != NULL && *p != '\0') {
680ed7bda5dSKevin Wolf return monitor_parse_command(hmp_mon, cmdp_start, cmdp, cmd->sub_table);
681ed7bda5dSKevin Wolf }
682ed7bda5dSKevin Wolf
683ed7bda5dSKevin Wolf return cmd;
684ed7bda5dSKevin Wolf }
685ed7bda5dSKevin Wolf
686ed7bda5dSKevin Wolf /*
687ed7bda5dSKevin Wolf * Parse arguments for @cmd.
688ed7bda5dSKevin Wolf * If it can't be parsed, report to @mon, and return NULL.
689ed7bda5dSKevin Wolf * Else, insert command arguments into a QDict, and return it.
690ed7bda5dSKevin Wolf * Note: On success, caller has to free the QDict structure.
691ed7bda5dSKevin Wolf */
monitor_parse_arguments(Monitor * mon,const char ** endp,const HMPCommand * cmd)692ed7bda5dSKevin Wolf static QDict *monitor_parse_arguments(Monitor *mon,
693ed7bda5dSKevin Wolf const char **endp,
694ed7bda5dSKevin Wolf const HMPCommand *cmd)
695ed7bda5dSKevin Wolf {
696ed7bda5dSKevin Wolf const char *typestr;
697ed7bda5dSKevin Wolf char *key;
698ed7bda5dSKevin Wolf int c;
699ed7bda5dSKevin Wolf const char *p = *endp;
700ed7bda5dSKevin Wolf char buf[1024];
701ed7bda5dSKevin Wolf QDict *qdict = qdict_new();
702ed7bda5dSKevin Wolf
703ed7bda5dSKevin Wolf /* parse the parameters */
704ed7bda5dSKevin Wolf typestr = cmd->args_type;
705ed7bda5dSKevin Wolf for (;;) {
706ed7bda5dSKevin Wolf typestr = key_get_info(typestr, &key);
707ed7bda5dSKevin Wolf if (!typestr) {
708ed7bda5dSKevin Wolf break;
709ed7bda5dSKevin Wolf }
710ed7bda5dSKevin Wolf c = *typestr;
711ed7bda5dSKevin Wolf typestr++;
712ed7bda5dSKevin Wolf switch (c) {
713ed7bda5dSKevin Wolf case 'F':
714ed7bda5dSKevin Wolf case 'B':
715ed7bda5dSKevin Wolf case 's':
716ed7bda5dSKevin Wolf {
717ed7bda5dSKevin Wolf int ret;
718ed7bda5dSKevin Wolf
719ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
720ed7bda5dSKevin Wolf p++;
721ed7bda5dSKevin Wolf }
722ed7bda5dSKevin Wolf if (*typestr == '?') {
723ed7bda5dSKevin Wolf typestr++;
724ed7bda5dSKevin Wolf if (*p == '\0') {
725ed7bda5dSKevin Wolf /* no optional string: NULL argument */
726ed7bda5dSKevin Wolf break;
727ed7bda5dSKevin Wolf }
728ed7bda5dSKevin Wolf }
729ed7bda5dSKevin Wolf ret = get_str(buf, sizeof(buf), &p);
730ed7bda5dSKevin Wolf if (ret < 0) {
731ed7bda5dSKevin Wolf switch (c) {
732ed7bda5dSKevin Wolf case 'F':
733ed7bda5dSKevin Wolf monitor_printf(mon, "%s: filename expected\n",
734ed7bda5dSKevin Wolf cmd->name);
735ed7bda5dSKevin Wolf break;
736ed7bda5dSKevin Wolf case 'B':
737ed7bda5dSKevin Wolf monitor_printf(mon, "%s: block device name expected\n",
738ed7bda5dSKevin Wolf cmd->name);
739ed7bda5dSKevin Wolf break;
740ed7bda5dSKevin Wolf default:
741ed7bda5dSKevin Wolf monitor_printf(mon, "%s: string expected\n", cmd->name);
742ed7bda5dSKevin Wolf break;
743ed7bda5dSKevin Wolf }
744ed7bda5dSKevin Wolf goto fail;
745ed7bda5dSKevin Wolf }
746ed7bda5dSKevin Wolf qdict_put_str(qdict, key, buf);
747ed7bda5dSKevin Wolf }
748ed7bda5dSKevin Wolf break;
749ed7bda5dSKevin Wolf case 'O':
750ed7bda5dSKevin Wolf {
751ed7bda5dSKevin Wolf QemuOptsList *opts_list;
752ed7bda5dSKevin Wolf QemuOpts *opts;
753ed7bda5dSKevin Wolf
754ed7bda5dSKevin Wolf opts_list = qemu_find_opts(key);
755ed7bda5dSKevin Wolf if (!opts_list || opts_list->desc->name) {
756ed7bda5dSKevin Wolf goto bad_type;
757ed7bda5dSKevin Wolf }
758ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
759ed7bda5dSKevin Wolf p++;
760ed7bda5dSKevin Wolf }
761ed7bda5dSKevin Wolf if (!*p) {
762ed7bda5dSKevin Wolf break;
763ed7bda5dSKevin Wolf }
764ed7bda5dSKevin Wolf if (get_str(buf, sizeof(buf), &p) < 0) {
765ed7bda5dSKevin Wolf goto fail;
766ed7bda5dSKevin Wolf }
767ed7bda5dSKevin Wolf opts = qemu_opts_parse_noisily(opts_list, buf, true);
768ed7bda5dSKevin Wolf if (!opts) {
769ed7bda5dSKevin Wolf goto fail;
770ed7bda5dSKevin Wolf }
771ed7bda5dSKevin Wolf qemu_opts_to_qdict(opts, qdict);
772ed7bda5dSKevin Wolf qemu_opts_del(opts);
773ed7bda5dSKevin Wolf }
774ed7bda5dSKevin Wolf break;
775ed7bda5dSKevin Wolf case '/':
776ed7bda5dSKevin Wolf {
777ed7bda5dSKevin Wolf int count, format, size;
778ed7bda5dSKevin Wolf
779ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
780ed7bda5dSKevin Wolf p++;
781ed7bda5dSKevin Wolf }
782ed7bda5dSKevin Wolf if (*p == '/') {
783ed7bda5dSKevin Wolf /* format found */
784ed7bda5dSKevin Wolf p++;
785ed7bda5dSKevin Wolf count = 1;
786ed7bda5dSKevin Wolf if (qemu_isdigit(*p)) {
787ed7bda5dSKevin Wolf count = 0;
788ed7bda5dSKevin Wolf while (qemu_isdigit(*p)) {
789ed7bda5dSKevin Wolf count = count * 10 + (*p - '0');
790ed7bda5dSKevin Wolf p++;
791ed7bda5dSKevin Wolf }
792ed7bda5dSKevin Wolf }
793ed7bda5dSKevin Wolf size = -1;
794ed7bda5dSKevin Wolf format = -1;
795ed7bda5dSKevin Wolf for (;;) {
796ed7bda5dSKevin Wolf switch (*p) {
797ed7bda5dSKevin Wolf case 'o':
798ed7bda5dSKevin Wolf case 'd':
799ed7bda5dSKevin Wolf case 'u':
800ed7bda5dSKevin Wolf case 'x':
801ed7bda5dSKevin Wolf case 'i':
802ed7bda5dSKevin Wolf case 'c':
803ed7bda5dSKevin Wolf format = *p++;
804ed7bda5dSKevin Wolf break;
805ed7bda5dSKevin Wolf case 'b':
806ed7bda5dSKevin Wolf size = 1;
807ed7bda5dSKevin Wolf p++;
808ed7bda5dSKevin Wolf break;
809ed7bda5dSKevin Wolf case 'h':
810ed7bda5dSKevin Wolf size = 2;
811ed7bda5dSKevin Wolf p++;
812ed7bda5dSKevin Wolf break;
813ed7bda5dSKevin Wolf case 'w':
814ed7bda5dSKevin Wolf size = 4;
815ed7bda5dSKevin Wolf p++;
816ed7bda5dSKevin Wolf break;
817ed7bda5dSKevin Wolf case 'g':
818ed7bda5dSKevin Wolf case 'L':
819ed7bda5dSKevin Wolf size = 8;
820ed7bda5dSKevin Wolf p++;
821ed7bda5dSKevin Wolf break;
822ed7bda5dSKevin Wolf default:
823ed7bda5dSKevin Wolf goto next;
824ed7bda5dSKevin Wolf }
825ed7bda5dSKevin Wolf }
826ed7bda5dSKevin Wolf next:
827ed7bda5dSKevin Wolf if (*p != '\0' && !qemu_isspace(*p)) {
828ed7bda5dSKevin Wolf monitor_printf(mon, "invalid char in format: '%c'\n",
829ed7bda5dSKevin Wolf *p);
830ed7bda5dSKevin Wolf goto fail;
831ed7bda5dSKevin Wolf }
832ed7bda5dSKevin Wolf if (format < 0) {
833ed7bda5dSKevin Wolf format = default_fmt_format;
834ed7bda5dSKevin Wolf }
835ed7bda5dSKevin Wolf if (format != 'i') {
836ed7bda5dSKevin Wolf /* for 'i', not specifying a size gives -1 as size */
837ed7bda5dSKevin Wolf if (size < 0) {
838ed7bda5dSKevin Wolf size = default_fmt_size;
839ed7bda5dSKevin Wolf }
840ed7bda5dSKevin Wolf default_fmt_size = size;
841ed7bda5dSKevin Wolf }
842ed7bda5dSKevin Wolf default_fmt_format = format;
843ed7bda5dSKevin Wolf } else {
844ed7bda5dSKevin Wolf count = 1;
845ed7bda5dSKevin Wolf format = default_fmt_format;
846ed7bda5dSKevin Wolf if (format != 'i') {
847ed7bda5dSKevin Wolf size = default_fmt_size;
848ed7bda5dSKevin Wolf } else {
849ed7bda5dSKevin Wolf size = -1;
850ed7bda5dSKevin Wolf }
851ed7bda5dSKevin Wolf }
852ed7bda5dSKevin Wolf qdict_put_int(qdict, "count", count);
853ed7bda5dSKevin Wolf qdict_put_int(qdict, "format", format);
854ed7bda5dSKevin Wolf qdict_put_int(qdict, "size", size);
855ed7bda5dSKevin Wolf }
856ed7bda5dSKevin Wolf break;
857ed7bda5dSKevin Wolf case 'i':
858ed7bda5dSKevin Wolf case 'l':
859ed7bda5dSKevin Wolf case 'M':
860ed7bda5dSKevin Wolf {
861ed7bda5dSKevin Wolf int64_t val;
862ed7bda5dSKevin Wolf
863ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
864ed7bda5dSKevin Wolf p++;
865ed7bda5dSKevin Wolf }
866ed7bda5dSKevin Wolf if (*typestr == '?' || *typestr == '.') {
867ed7bda5dSKevin Wolf if (*typestr == '?') {
868ed7bda5dSKevin Wolf if (*p == '\0') {
869ed7bda5dSKevin Wolf typestr++;
870ed7bda5dSKevin Wolf break;
871ed7bda5dSKevin Wolf }
872ed7bda5dSKevin Wolf } else {
873ed7bda5dSKevin Wolf if (*p == '.') {
874ed7bda5dSKevin Wolf p++;
875ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
876ed7bda5dSKevin Wolf p++;
877ed7bda5dSKevin Wolf }
878ed7bda5dSKevin Wolf } else {
879ed7bda5dSKevin Wolf typestr++;
880ed7bda5dSKevin Wolf break;
881ed7bda5dSKevin Wolf }
882ed7bda5dSKevin Wolf }
883ed7bda5dSKevin Wolf typestr++;
884ed7bda5dSKevin Wolf }
885ed7bda5dSKevin Wolf if (get_expr(mon, &val, &p)) {
886ed7bda5dSKevin Wolf goto fail;
887ed7bda5dSKevin Wolf }
888ed7bda5dSKevin Wolf /* Check if 'i' is greater than 32-bit */
889ed7bda5dSKevin Wolf if ((c == 'i') && ((val >> 32) & 0xffffffff)) {
890ed7bda5dSKevin Wolf monitor_printf(mon, "\'%s\' has failed: ", cmd->name);
891ed7bda5dSKevin Wolf monitor_printf(mon, "integer is for 32-bit values\n");
892ed7bda5dSKevin Wolf goto fail;
893ed7bda5dSKevin Wolf } else if (c == 'M') {
894ed7bda5dSKevin Wolf if (val < 0) {
895ed7bda5dSKevin Wolf monitor_printf(mon, "enter a positive value\n");
896ed7bda5dSKevin Wolf goto fail;
897ed7bda5dSKevin Wolf }
898ed7bda5dSKevin Wolf val *= MiB;
899ed7bda5dSKevin Wolf }
900ed7bda5dSKevin Wolf qdict_put_int(qdict, key, val);
901ed7bda5dSKevin Wolf }
902ed7bda5dSKevin Wolf break;
903ed7bda5dSKevin Wolf case 'o':
904ed7bda5dSKevin Wolf {
905ed7bda5dSKevin Wolf int ret;
906ed7bda5dSKevin Wolf uint64_t val;
907ed7bda5dSKevin Wolf const char *end;
908ed7bda5dSKevin Wolf
909ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
910ed7bda5dSKevin Wolf p++;
911ed7bda5dSKevin Wolf }
912ed7bda5dSKevin Wolf if (*typestr == '?') {
913ed7bda5dSKevin Wolf typestr++;
914ed7bda5dSKevin Wolf if (*p == '\0') {
915ed7bda5dSKevin Wolf break;
916ed7bda5dSKevin Wolf }
917ed7bda5dSKevin Wolf }
918ed7bda5dSKevin Wolf ret = qemu_strtosz_MiB(p, &end, &val);
919ed7bda5dSKevin Wolf if (ret < 0 || val > INT64_MAX) {
920ed7bda5dSKevin Wolf monitor_printf(mon, "invalid size\n");
921ed7bda5dSKevin Wolf goto fail;
922ed7bda5dSKevin Wolf }
923ed7bda5dSKevin Wolf qdict_put_int(qdict, key, val);
924ed7bda5dSKevin Wolf p = end;
925ed7bda5dSKevin Wolf }
926ed7bda5dSKevin Wolf break;
927ed7bda5dSKevin Wolf case 'T':
928ed7bda5dSKevin Wolf {
929ed7bda5dSKevin Wolf double val;
930ed7bda5dSKevin Wolf
931ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
932ed7bda5dSKevin Wolf p++;
933ed7bda5dSKevin Wolf }
934ed7bda5dSKevin Wolf if (*typestr == '?') {
935ed7bda5dSKevin Wolf typestr++;
936ed7bda5dSKevin Wolf if (*p == '\0') {
937ed7bda5dSKevin Wolf break;
938ed7bda5dSKevin Wolf }
939ed7bda5dSKevin Wolf }
940ed7bda5dSKevin Wolf if (get_double(mon, &val, &p) < 0) {
941ed7bda5dSKevin Wolf goto fail;
942ed7bda5dSKevin Wolf }
943ed7bda5dSKevin Wolf if (p[0] && p[1] == 's') {
944ed7bda5dSKevin Wolf switch (*p) {
945ed7bda5dSKevin Wolf case 'm':
946ed7bda5dSKevin Wolf val /= 1e3; p += 2; break;
947ed7bda5dSKevin Wolf case 'u':
948ed7bda5dSKevin Wolf val /= 1e6; p += 2; break;
949ed7bda5dSKevin Wolf case 'n':
950ed7bda5dSKevin Wolf val /= 1e9; p += 2; break;
951ed7bda5dSKevin Wolf }
952ed7bda5dSKevin Wolf }
953ed7bda5dSKevin Wolf if (*p && !qemu_isspace(*p)) {
954ed7bda5dSKevin Wolf monitor_printf(mon, "Unknown unit suffix\n");
955ed7bda5dSKevin Wolf goto fail;
956ed7bda5dSKevin Wolf }
957ed7bda5dSKevin Wolf qdict_put(qdict, key, qnum_from_double(val));
958ed7bda5dSKevin Wolf }
959ed7bda5dSKevin Wolf break;
960ed7bda5dSKevin Wolf case 'b':
961ed7bda5dSKevin Wolf {
962ed7bda5dSKevin Wolf const char *beg;
963ed7bda5dSKevin Wolf bool val;
964ed7bda5dSKevin Wolf
965ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
966ed7bda5dSKevin Wolf p++;
967ed7bda5dSKevin Wolf }
968ed7bda5dSKevin Wolf beg = p;
969ed7bda5dSKevin Wolf while (qemu_isgraph(*p)) {
970ed7bda5dSKevin Wolf p++;
971ed7bda5dSKevin Wolf }
972ed7bda5dSKevin Wolf if (p - beg == 2 && !memcmp(beg, "on", p - beg)) {
973ed7bda5dSKevin Wolf val = true;
974ed7bda5dSKevin Wolf } else if (p - beg == 3 && !memcmp(beg, "off", p - beg)) {
975ed7bda5dSKevin Wolf val = false;
976ed7bda5dSKevin Wolf } else {
977ed7bda5dSKevin Wolf monitor_printf(mon, "Expected 'on' or 'off'\n");
978ed7bda5dSKevin Wolf goto fail;
979ed7bda5dSKevin Wolf }
980ed7bda5dSKevin Wolf qdict_put_bool(qdict, key, val);
981ed7bda5dSKevin Wolf }
982ed7bda5dSKevin Wolf break;
983ed7bda5dSKevin Wolf case '-':
984ed7bda5dSKevin Wolf {
985ed7bda5dSKevin Wolf const char *tmp = p;
986ed7bda5dSKevin Wolf int skip_key = 0;
98726fcd766SStefan Reiter int ret;
988ed7bda5dSKevin Wolf /* option */
989ed7bda5dSKevin Wolf
990ed7bda5dSKevin Wolf c = *typestr++;
991ed7bda5dSKevin Wolf if (c == '\0') {
992ed7bda5dSKevin Wolf goto bad_type;
993ed7bda5dSKevin Wolf }
994ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
995ed7bda5dSKevin Wolf p++;
996ed7bda5dSKevin Wolf }
997ed7bda5dSKevin Wolf if (*p == '-') {
998ed7bda5dSKevin Wolf p++;
999ed7bda5dSKevin Wolf if (c != *p) {
1000ed7bda5dSKevin Wolf if (!is_valid_option(p, typestr)) {
1001ed7bda5dSKevin Wolf monitor_printf(mon, "%s: unsupported option -%c\n",
1002ed7bda5dSKevin Wolf cmd->name, *p);
1003ed7bda5dSKevin Wolf goto fail;
1004ed7bda5dSKevin Wolf } else {
1005ed7bda5dSKevin Wolf skip_key = 1;
1006ed7bda5dSKevin Wolf }
1007ed7bda5dSKevin Wolf }
1008ed7bda5dSKevin Wolf if (skip_key) {
1009ed7bda5dSKevin Wolf p = tmp;
101026fcd766SStefan Reiter } else if (*typestr == 's') {
101126fcd766SStefan Reiter /* has option with string value */
101226fcd766SStefan Reiter typestr++;
101326fcd766SStefan Reiter tmp = p++;
101426fcd766SStefan Reiter while (qemu_isspace(*p)) {
101526fcd766SStefan Reiter p++;
101626fcd766SStefan Reiter }
101726fcd766SStefan Reiter ret = get_str(buf, sizeof(buf), &p);
101826fcd766SStefan Reiter if (ret < 0) {
101926fcd766SStefan Reiter monitor_printf(mon, "%s: value expected for -%c\n",
102026fcd766SStefan Reiter cmd->name, *tmp);
102126fcd766SStefan Reiter goto fail;
102226fcd766SStefan Reiter }
102326fcd766SStefan Reiter qdict_put_str(qdict, key, buf);
1024ed7bda5dSKevin Wolf } else {
102526fcd766SStefan Reiter /* has boolean option */
1026ed7bda5dSKevin Wolf p++;
1027ed7bda5dSKevin Wolf qdict_put_bool(qdict, key, true);
1028ed7bda5dSKevin Wolf }
102926fcd766SStefan Reiter } else if (*typestr == 's') {
103026fcd766SStefan Reiter typestr++;
1031ed7bda5dSKevin Wolf }
1032ed7bda5dSKevin Wolf }
1033ed7bda5dSKevin Wolf break;
1034ed7bda5dSKevin Wolf case 'S':
1035ed7bda5dSKevin Wolf {
1036ed7bda5dSKevin Wolf /* package all remaining string */
1037ed7bda5dSKevin Wolf int len;
1038ed7bda5dSKevin Wolf
1039ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
1040ed7bda5dSKevin Wolf p++;
1041ed7bda5dSKevin Wolf }
1042ed7bda5dSKevin Wolf if (*typestr == '?') {
1043ed7bda5dSKevin Wolf typestr++;
1044ed7bda5dSKevin Wolf if (*p == '\0') {
1045ed7bda5dSKevin Wolf /* no remaining string: NULL argument */
1046ed7bda5dSKevin Wolf break;
1047ed7bda5dSKevin Wolf }
1048ed7bda5dSKevin Wolf }
1049ed7bda5dSKevin Wolf len = strlen(p);
1050ed7bda5dSKevin Wolf if (len <= 0) {
1051ed7bda5dSKevin Wolf monitor_printf(mon, "%s: string expected\n",
1052ed7bda5dSKevin Wolf cmd->name);
1053ed7bda5dSKevin Wolf goto fail;
1054ed7bda5dSKevin Wolf }
1055ed7bda5dSKevin Wolf qdict_put_str(qdict, key, p);
1056ed7bda5dSKevin Wolf p += len;
1057ed7bda5dSKevin Wolf }
1058ed7bda5dSKevin Wolf break;
1059ed7bda5dSKevin Wolf default:
1060ed7bda5dSKevin Wolf bad_type:
1061ed7bda5dSKevin Wolf monitor_printf(mon, "%s: unknown type '%c'\n", cmd->name, c);
1062ed7bda5dSKevin Wolf goto fail;
1063ed7bda5dSKevin Wolf }
1064ed7bda5dSKevin Wolf g_free(key);
1065ed7bda5dSKevin Wolf key = NULL;
1066ed7bda5dSKevin Wolf }
1067ed7bda5dSKevin Wolf /* check that all arguments were parsed */
1068ed7bda5dSKevin Wolf while (qemu_isspace(*p)) {
1069ed7bda5dSKevin Wolf p++;
1070ed7bda5dSKevin Wolf }
1071ed7bda5dSKevin Wolf if (*p != '\0') {
1072ed7bda5dSKevin Wolf monitor_printf(mon, "%s: extraneous characters at the end of line\n",
1073ed7bda5dSKevin Wolf cmd->name);
1074ed7bda5dSKevin Wolf goto fail;
1075ed7bda5dSKevin Wolf }
1076ed7bda5dSKevin Wolf
1077ed7bda5dSKevin Wolf return qdict;
1078ed7bda5dSKevin Wolf
1079ed7bda5dSKevin Wolf fail:
1080ed7bda5dSKevin Wolf qobject_unref(qdict);
1081ed7bda5dSKevin Wolf g_free(key);
1082ed7bda5dSKevin Wolf return NULL;
1083ed7bda5dSKevin Wolf }
1084ed7bda5dSKevin Wolf
hmp_info_human_readable_text(Monitor * mon,HumanReadableText * (* handler)(Error **))1085f9429c67SDaniel P. Berrangé static void hmp_info_human_readable_text(Monitor *mon,
1086f9429c67SDaniel P. Berrangé HumanReadableText *(*handler)(Error **))
1087f9429c67SDaniel P. Berrangé {
1088f9429c67SDaniel P. Berrangé Error *err = NULL;
1089f9429c67SDaniel P. Berrangé g_autoptr(HumanReadableText) info = handler(&err);
1090f9429c67SDaniel P. Berrangé
1091f9429c67SDaniel P. Berrangé if (hmp_handle_error(mon, err)) {
1092f9429c67SDaniel P. Berrangé return;
1093f9429c67SDaniel P. Berrangé }
1094f9429c67SDaniel P. Berrangé
1095bf0c50d4SAlex Bennée monitor_puts(mon, info->human_readable_text);
1096f9429c67SDaniel P. Berrangé }
1097f9429c67SDaniel P. Berrangé
handle_hmp_command_exec(Monitor * mon,const HMPCommand * cmd,QDict * qdict)1098f9429c67SDaniel P. Berrangé static void handle_hmp_command_exec(Monitor *mon,
1099f9429c67SDaniel P. Berrangé const HMPCommand *cmd,
1100f9429c67SDaniel P. Berrangé QDict *qdict)
1101f9429c67SDaniel P. Berrangé {
1102f9429c67SDaniel P. Berrangé if (cmd->cmd_info_hrt) {
1103f9429c67SDaniel P. Berrangé hmp_info_human_readable_text(mon,
1104f9429c67SDaniel P. Berrangé cmd->cmd_info_hrt);
1105f9429c67SDaniel P. Berrangé } else {
1106f9429c67SDaniel P. Berrangé cmd->cmd(mon, qdict);
1107f9429c67SDaniel P. Berrangé }
1108f9429c67SDaniel P. Berrangé }
1109f9429c67SDaniel P. Berrangé
1110bb4b9eadSKevin Wolf typedef struct HandleHmpCommandCo {
1111bb4b9eadSKevin Wolf Monitor *mon;
1112bb4b9eadSKevin Wolf const HMPCommand *cmd;
1113bb4b9eadSKevin Wolf QDict *qdict;
1114bb4b9eadSKevin Wolf bool done;
1115bb4b9eadSKevin Wolf } HandleHmpCommandCo;
1116bb4b9eadSKevin Wolf
handle_hmp_command_co(void * opaque)1117bb4b9eadSKevin Wolf static void handle_hmp_command_co(void *opaque)
1118bb4b9eadSKevin Wolf {
1119bb4b9eadSKevin Wolf HandleHmpCommandCo *data = opaque;
1120f9429c67SDaniel P. Berrangé handle_hmp_command_exec(data->mon, data->cmd, data->qdict);
1121bb4b9eadSKevin Wolf monitor_set_cur(qemu_coroutine_self(), NULL);
1122bb4b9eadSKevin Wolf data->done = true;
1123bb4b9eadSKevin Wolf }
1124bb4b9eadSKevin Wolf
handle_hmp_command(MonitorHMP * mon,const char * cmdline)1125ed7bda5dSKevin Wolf void handle_hmp_command(MonitorHMP *mon, const char *cmdline)
1126ed7bda5dSKevin Wolf {
1127ed7bda5dSKevin Wolf QDict *qdict;
1128ed7bda5dSKevin Wolf const HMPCommand *cmd;
1129ed7bda5dSKevin Wolf const char *cmd_start = cmdline;
1130ed7bda5dSKevin Wolf
1131ed7bda5dSKevin Wolf trace_handle_hmp_command(mon, cmdline);
1132ed7bda5dSKevin Wolf
1133ed7bda5dSKevin Wolf cmd = monitor_parse_command(mon, cmdline, &cmdline, hmp_cmds);
1134ed7bda5dSKevin Wolf if (!cmd) {
1135ed7bda5dSKevin Wolf return;
1136ed7bda5dSKevin Wolf }
1137ed7bda5dSKevin Wolf
1138f9429c67SDaniel P. Berrangé if (!cmd->cmd && !cmd->cmd_info_hrt) {
1139f0e48cbdSGerd Hoffmann /* FIXME: is it useful to try autoload modules here ??? */
1140f0e48cbdSGerd Hoffmann monitor_printf(&mon->common, "Command \"%.*s\" is not available.\n",
1141f0e48cbdSGerd Hoffmann (int)(cmdline - cmd_start), cmd_start);
1142f0e48cbdSGerd Hoffmann return;
1143f0e48cbdSGerd Hoffmann }
1144f0e48cbdSGerd Hoffmann
1145ed7bda5dSKevin Wolf qdict = monitor_parse_arguments(&mon->common, &cmdline, cmd);
1146ed7bda5dSKevin Wolf if (!qdict) {
1147ed7bda5dSKevin Wolf while (cmdline > cmd_start && qemu_isspace(cmdline[-1])) {
1148ed7bda5dSKevin Wolf cmdline--;
1149ed7bda5dSKevin Wolf }
1150ed7bda5dSKevin Wolf monitor_printf(&mon->common, "Try \"help %.*s\" for more information\n",
1151ed7bda5dSKevin Wolf (int)(cmdline - cmd_start), cmd_start);
1152ed7bda5dSKevin Wolf return;
1153ed7bda5dSKevin Wolf }
1154ed7bda5dSKevin Wolf
1155bb4b9eadSKevin Wolf if (!cmd->coroutine) {
1156ff04108aSKevin Wolf /* old_mon is non-NULL when called from qmp_human_monitor_command() */
1157bb4b9eadSKevin Wolf Monitor *old_mon = monitor_set_cur(qemu_coroutine_self(), &mon->common);
1158f9429c67SDaniel P. Berrangé handle_hmp_command_exec(&mon->common, cmd, qdict);
1159e69ee454SKevin Wolf monitor_set_cur(qemu_coroutine_self(), old_mon);
1160bb4b9eadSKevin Wolf } else {
1161bb4b9eadSKevin Wolf HandleHmpCommandCo data = {
1162bb4b9eadSKevin Wolf .mon = &mon->common,
1163bb4b9eadSKevin Wolf .cmd = cmd,
1164bb4b9eadSKevin Wolf .qdict = qdict,
1165bb4b9eadSKevin Wolf .done = false,
1166bb4b9eadSKevin Wolf };
1167bb4b9eadSKevin Wolf Coroutine *co = qemu_coroutine_create(handle_hmp_command_co, &data);
1168bb4b9eadSKevin Wolf monitor_set_cur(co, &mon->common);
1169bb4b9eadSKevin Wolf aio_co_enter(qemu_get_aio_context(), co);
11706bb68553SStefan Hajnoczi AIO_WAIT_WHILE_UNLOCKED(NULL, !data.done);
1171bb4b9eadSKevin Wolf }
1172ff04108aSKevin Wolf
1173ed7bda5dSKevin Wolf qobject_unref(qdict);
1174ed7bda5dSKevin Wolf }
1175ed7bda5dSKevin Wolf
cmd_completion(MonitorHMP * mon,const char * name,const char * list)1176ed7bda5dSKevin Wolf static void cmd_completion(MonitorHMP *mon, const char *name, const char *list)
1177ed7bda5dSKevin Wolf {
1178ed7bda5dSKevin Wolf const char *p, *pstart;
1179ed7bda5dSKevin Wolf char cmd[128];
1180ed7bda5dSKevin Wolf int len;
1181ed7bda5dSKevin Wolf
1182ed7bda5dSKevin Wolf p = list;
1183ed7bda5dSKevin Wolf for (;;) {
1184ed7bda5dSKevin Wolf pstart = p;
1185ed7bda5dSKevin Wolf p = qemu_strchrnul(p, '|');
1186ed7bda5dSKevin Wolf len = p - pstart;
1187ed7bda5dSKevin Wolf if (len > sizeof(cmd) - 2) {
1188ed7bda5dSKevin Wolf len = sizeof(cmd) - 2;
1189ed7bda5dSKevin Wolf }
1190ed7bda5dSKevin Wolf memcpy(cmd, pstart, len);
1191ed7bda5dSKevin Wolf cmd[len] = '\0';
119252f50b1eSMarkus Armbruster readline_add_completion_of(mon->rs, name, cmd);
1193ed7bda5dSKevin Wolf if (*p == '\0') {
1194ed7bda5dSKevin Wolf break;
1195ed7bda5dSKevin Wolf }
1196ed7bda5dSKevin Wolf p++;
1197ed7bda5dSKevin Wolf }
1198ed7bda5dSKevin Wolf }
1199ed7bda5dSKevin Wolf
file_completion(MonitorHMP * mon,const char * input)1200ed7bda5dSKevin Wolf static void file_completion(MonitorHMP *mon, const char *input)
1201ed7bda5dSKevin Wolf {
1202ed7bda5dSKevin Wolf DIR *ffs;
1203ed7bda5dSKevin Wolf struct dirent *d;
1204ed7bda5dSKevin Wolf char path[1024];
1205ed7bda5dSKevin Wolf char file[1024], file_prefix[1024];
1206ed7bda5dSKevin Wolf int input_path_len;
1207ed7bda5dSKevin Wolf const char *p;
1208ed7bda5dSKevin Wolf
1209ed7bda5dSKevin Wolf p = strrchr(input, '/');
1210ed7bda5dSKevin Wolf if (!p) {
1211ed7bda5dSKevin Wolf input_path_len = 0;
1212ed7bda5dSKevin Wolf pstrcpy(file_prefix, sizeof(file_prefix), input);
1213ed7bda5dSKevin Wolf pstrcpy(path, sizeof(path), ".");
1214ed7bda5dSKevin Wolf } else {
1215ed7bda5dSKevin Wolf input_path_len = p - input + 1;
1216ed7bda5dSKevin Wolf memcpy(path, input, input_path_len);
1217ed7bda5dSKevin Wolf if (input_path_len > sizeof(path) - 1) {
1218ed7bda5dSKevin Wolf input_path_len = sizeof(path) - 1;
1219ed7bda5dSKevin Wolf }
1220ed7bda5dSKevin Wolf path[input_path_len] = '\0';
1221ed7bda5dSKevin Wolf pstrcpy(file_prefix, sizeof(file_prefix), p + 1);
1222ed7bda5dSKevin Wolf }
1223ed7bda5dSKevin Wolf
1224ed7bda5dSKevin Wolf ffs = opendir(path);
1225ed7bda5dSKevin Wolf if (!ffs) {
1226ed7bda5dSKevin Wolf return;
1227ed7bda5dSKevin Wolf }
1228ed7bda5dSKevin Wolf for (;;) {
1229ed7bda5dSKevin Wolf struct stat sb;
1230ed7bda5dSKevin Wolf d = readdir(ffs);
1231ed7bda5dSKevin Wolf if (!d) {
1232ed7bda5dSKevin Wolf break;
1233ed7bda5dSKevin Wolf }
1234ed7bda5dSKevin Wolf
1235ed7bda5dSKevin Wolf if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) {
1236ed7bda5dSKevin Wolf continue;
1237ed7bda5dSKevin Wolf }
1238ed7bda5dSKevin Wolf
1239ed7bda5dSKevin Wolf if (strstart(d->d_name, file_prefix, NULL)) {
1240ed7bda5dSKevin Wolf memcpy(file, input, input_path_len);
1241ed7bda5dSKevin Wolf if (input_path_len < sizeof(file)) {
1242ed7bda5dSKevin Wolf pstrcpy(file + input_path_len, sizeof(file) - input_path_len,
1243ed7bda5dSKevin Wolf d->d_name);
1244ed7bda5dSKevin Wolf }
1245ed7bda5dSKevin Wolf /*
1246ed7bda5dSKevin Wolf * stat the file to find out if it's a directory.
1247ed7bda5dSKevin Wolf * In that case add a slash to speed up typing long paths
1248ed7bda5dSKevin Wolf */
1249ed7bda5dSKevin Wolf if (stat(file, &sb) == 0 && S_ISDIR(sb.st_mode)) {
1250ed7bda5dSKevin Wolf pstrcat(file, sizeof(file), "/");
1251ed7bda5dSKevin Wolf }
1252ed7bda5dSKevin Wolf readline_add_completion(mon->rs, file);
1253ed7bda5dSKevin Wolf }
1254ed7bda5dSKevin Wolf }
1255ed7bda5dSKevin Wolf closedir(ffs);
1256ed7bda5dSKevin Wolf }
1257ed7bda5dSKevin Wolf
next_arg_type(const char * typestr)1258ed7bda5dSKevin Wolf static const char *next_arg_type(const char *typestr)
1259ed7bda5dSKevin Wolf {
1260ed7bda5dSKevin Wolf const char *p = strchr(typestr, ':');
1261ed7bda5dSKevin Wolf return (p != NULL ? ++p : typestr);
1262ed7bda5dSKevin Wolf }
1263ed7bda5dSKevin Wolf
monitor_find_completion_by_table(MonitorHMP * mon,const HMPCommand * cmd_table,char ** args,int nb_args)1264ed7bda5dSKevin Wolf static void monitor_find_completion_by_table(MonitorHMP *mon,
1265ed7bda5dSKevin Wolf const HMPCommand *cmd_table,
1266ed7bda5dSKevin Wolf char **args,
1267ed7bda5dSKevin Wolf int nb_args)
1268ed7bda5dSKevin Wolf {
1269ed7bda5dSKevin Wolf const char *cmdname;
1270ed7bda5dSKevin Wolf int i;
127152f50b1eSMarkus Armbruster const char *ptype, *old_ptype, *str;
1272ed7bda5dSKevin Wolf const HMPCommand *cmd;
1273ed7bda5dSKevin Wolf BlockBackend *blk = NULL;
1274ed7bda5dSKevin Wolf
1275ed7bda5dSKevin Wolf if (nb_args <= 1) {
1276ed7bda5dSKevin Wolf /* command completion */
1277ed7bda5dSKevin Wolf if (nb_args == 0) {
1278ed7bda5dSKevin Wolf cmdname = "";
1279ed7bda5dSKevin Wolf } else {
1280ed7bda5dSKevin Wolf cmdname = args[0];
1281ed7bda5dSKevin Wolf }
1282ed7bda5dSKevin Wolf readline_set_completion_index(mon->rs, strlen(cmdname));
1283ed7bda5dSKevin Wolf for (cmd = cmd_table; cmd->name != NULL; cmd++) {
12844cd29274SPaolo Bonzini if (cmd_available(cmd)) {
1285ed7bda5dSKevin Wolf cmd_completion(mon, cmdname, cmd->name);
1286ed7bda5dSKevin Wolf }
1287ed7bda5dSKevin Wolf }
1288ed7bda5dSKevin Wolf } else {
1289ed7bda5dSKevin Wolf /* find the command */
1290ed7bda5dSKevin Wolf for (cmd = cmd_table; cmd->name != NULL; cmd++) {
1291ed7bda5dSKevin Wolf if (hmp_compare_cmd(args[0], cmd->name) &&
12924cd29274SPaolo Bonzini cmd_available(cmd)) {
1293ed7bda5dSKevin Wolf break;
1294ed7bda5dSKevin Wolf }
1295ed7bda5dSKevin Wolf }
1296ed7bda5dSKevin Wolf if (!cmd->name) {
1297ed7bda5dSKevin Wolf return;
1298ed7bda5dSKevin Wolf }
1299ed7bda5dSKevin Wolf
1300ed7bda5dSKevin Wolf if (cmd->sub_table) {
1301ed7bda5dSKevin Wolf /* do the job again */
1302ed7bda5dSKevin Wolf monitor_find_completion_by_table(mon, cmd->sub_table,
1303ed7bda5dSKevin Wolf &args[1], nb_args - 1);
1304ed7bda5dSKevin Wolf return;
1305ed7bda5dSKevin Wolf }
1306ed7bda5dSKevin Wolf if (cmd->command_completion) {
1307ed7bda5dSKevin Wolf cmd->command_completion(mon->rs, nb_args, args[nb_args - 1]);
1308ed7bda5dSKevin Wolf return;
1309ed7bda5dSKevin Wolf }
1310ed7bda5dSKevin Wolf
1311ed7bda5dSKevin Wolf ptype = next_arg_type(cmd->args_type);
1312ed7bda5dSKevin Wolf for (i = 0; i < nb_args - 2; i++) {
1313ed7bda5dSKevin Wolf if (*ptype != '\0') {
1314ed7bda5dSKevin Wolf ptype = next_arg_type(ptype);
1315ed7bda5dSKevin Wolf while (*ptype == '?') {
1316ed7bda5dSKevin Wolf ptype = next_arg_type(ptype);
1317ed7bda5dSKevin Wolf }
1318ed7bda5dSKevin Wolf }
1319ed7bda5dSKevin Wolf }
1320ed7bda5dSKevin Wolf str = args[nb_args - 1];
1321ed7bda5dSKevin Wolf old_ptype = NULL;
1322ed7bda5dSKevin Wolf while (*ptype == '-' && old_ptype != ptype) {
1323ed7bda5dSKevin Wolf old_ptype = ptype;
1324ed7bda5dSKevin Wolf ptype = next_arg_type(ptype);
1325ed7bda5dSKevin Wolf }
1326ed7bda5dSKevin Wolf switch (*ptype) {
1327ed7bda5dSKevin Wolf case 'F':
1328ed7bda5dSKevin Wolf /* file completion */
1329ed7bda5dSKevin Wolf readline_set_completion_index(mon->rs, strlen(str));
1330ed7bda5dSKevin Wolf file_completion(mon, str);
1331ed7bda5dSKevin Wolf break;
1332ed7bda5dSKevin Wolf case 'B':
1333ed7bda5dSKevin Wolf /* block device name completion */
1334ed7bda5dSKevin Wolf readline_set_completion_index(mon->rs, strlen(str));
1335ed7bda5dSKevin Wolf while ((blk = blk_next(blk)) != NULL) {
133652f50b1eSMarkus Armbruster readline_add_completion_of(mon->rs, str, blk_name(blk));
1337ed7bda5dSKevin Wolf }
1338ed7bda5dSKevin Wolf break;
1339ed7bda5dSKevin Wolf case 's':
1340ed7bda5dSKevin Wolf case 'S':
1341ed7bda5dSKevin Wolf if (!strcmp(cmd->name, "help|?")) {
1342ed7bda5dSKevin Wolf monitor_find_completion_by_table(mon, cmd_table,
1343ed7bda5dSKevin Wolf &args[1], nb_args - 1);
1344ed7bda5dSKevin Wolf }
1345ed7bda5dSKevin Wolf break;
1346ed7bda5dSKevin Wolf default:
1347ed7bda5dSKevin Wolf break;
1348ed7bda5dSKevin Wolf }
1349ed7bda5dSKevin Wolf }
1350ed7bda5dSKevin Wolf }
1351ed7bda5dSKevin Wolf
monitor_find_completion(void * opaque,const char * cmdline)1352ed7bda5dSKevin Wolf static void monitor_find_completion(void *opaque,
1353ed7bda5dSKevin Wolf const char *cmdline)
1354ed7bda5dSKevin Wolf {
1355ed7bda5dSKevin Wolf MonitorHMP *mon = opaque;
1356ed7bda5dSKevin Wolf char *args[MAX_ARGS];
1357ed7bda5dSKevin Wolf int nb_args, len;
1358ed7bda5dSKevin Wolf
1359ed7bda5dSKevin Wolf /* 1. parse the cmdline */
1360ed7bda5dSKevin Wolf if (parse_cmdline(cmdline, &nb_args, args) < 0) {
1361ed7bda5dSKevin Wolf return;
1362ed7bda5dSKevin Wolf }
1363ed7bda5dSKevin Wolf
1364ed7bda5dSKevin Wolf /*
1365ed7bda5dSKevin Wolf * if the line ends with a space, it means we want to complete the
1366ed7bda5dSKevin Wolf * next arg
1367ed7bda5dSKevin Wolf */
1368ed7bda5dSKevin Wolf len = strlen(cmdline);
1369ed7bda5dSKevin Wolf if (len > 0 && qemu_isspace(cmdline[len - 1])) {
1370ed7bda5dSKevin Wolf if (nb_args >= MAX_ARGS) {
1371ed7bda5dSKevin Wolf goto cleanup;
1372ed7bda5dSKevin Wolf }
1373ed7bda5dSKevin Wolf args[nb_args++] = g_strdup("");
1374ed7bda5dSKevin Wolf }
1375ed7bda5dSKevin Wolf
1376ed7bda5dSKevin Wolf /* 2. auto complete according to args */
1377ed7bda5dSKevin Wolf monitor_find_completion_by_table(mon, hmp_cmds, args, nb_args);
1378ed7bda5dSKevin Wolf
1379ed7bda5dSKevin Wolf cleanup:
1380ed7bda5dSKevin Wolf free_cmdline_args(args, nb_args);
1381ed7bda5dSKevin Wolf }
1382ed7bda5dSKevin Wolf
monitor_read(void * opaque,const uint8_t * buf,int size)1383ed7bda5dSKevin Wolf static void monitor_read(void *opaque, const uint8_t *buf, int size)
1384ed7bda5dSKevin Wolf {
1385947e4744SKevin Wolf MonitorHMP *mon = container_of(opaque, MonitorHMP, common);
1386ed7bda5dSKevin Wolf int i;
1387ed7bda5dSKevin Wolf
1388ed7bda5dSKevin Wolf if (mon->rs) {
1389ed7bda5dSKevin Wolf for (i = 0; i < size; i++) {
1390ed7bda5dSKevin Wolf readline_handle_byte(mon->rs, buf[i]);
1391ed7bda5dSKevin Wolf }
1392ed7bda5dSKevin Wolf } else {
1393ed7bda5dSKevin Wolf if (size == 0 || buf[size - 1] != 0) {
1394947e4744SKevin Wolf monitor_printf(&mon->common, "corrupted command\n");
1395ed7bda5dSKevin Wolf } else {
1396ed7bda5dSKevin Wolf handle_hmp_command(mon, (char *)buf);
1397ed7bda5dSKevin Wolf }
1398ed7bda5dSKevin Wolf }
1399ed7bda5dSKevin Wolf }
1400ed7bda5dSKevin Wolf
monitor_event(void * opaque,QEMUChrEvent event)1401083b266fSPhilippe Mathieu-Daudé static void monitor_event(void *opaque, QEMUChrEvent event)
1402ed7bda5dSKevin Wolf {
1403ed7bda5dSKevin Wolf Monitor *mon = opaque;
1404ed7bda5dSKevin Wolf
1405ed7bda5dSKevin Wolf switch (event) {
1406ed7bda5dSKevin Wolf case CHR_EVENT_MUX_IN:
1407ed7bda5dSKevin Wolf qemu_mutex_lock(&mon->mon_lock);
1408*6ee7c82dSPaolo Bonzini if (mon->mux_out) {
1409ed7bda5dSKevin Wolf mon->mux_out = 0;
1410ed7bda5dSKevin Wolf monitor_resume(mon);
1411ed7bda5dSKevin Wolf }
1412*6ee7c82dSPaolo Bonzini qemu_mutex_unlock(&mon->mon_lock);
1413ed7bda5dSKevin Wolf break;
1414ed7bda5dSKevin Wolf
1415ed7bda5dSKevin Wolf case CHR_EVENT_MUX_OUT:
1416ed7bda5dSKevin Wolf qemu_mutex_lock(&mon->mon_lock);
1417*6ee7c82dSPaolo Bonzini if (!mon->mux_out) {
1418*6ee7c82dSPaolo Bonzini if (mon->reset_seen && !mon->suspend_cnt) {
1419*6ee7c82dSPaolo Bonzini monitor_puts_locked(mon, "\n");
1420*6ee7c82dSPaolo Bonzini } else {
1421*6ee7c82dSPaolo Bonzini monitor_flush_locked(mon);
1422*6ee7c82dSPaolo Bonzini }
1423*6ee7c82dSPaolo Bonzini monitor_suspend(mon);
1424ed7bda5dSKevin Wolf mon->mux_out = 1;
1425*6ee7c82dSPaolo Bonzini }
1426ed7bda5dSKevin Wolf qemu_mutex_unlock(&mon->mon_lock);
1427ed7bda5dSKevin Wolf break;
1428ed7bda5dSKevin Wolf
1429ed7bda5dSKevin Wolf case CHR_EVENT_OPENED:
1430ed7bda5dSKevin Wolf monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
1431ed7bda5dSKevin Wolf "information\n", QEMU_VERSION);
1432*6ee7c82dSPaolo Bonzini qemu_mutex_lock(&mon->mon_lock);
1433ed7bda5dSKevin Wolf mon->reset_seen = 1;
1434*6ee7c82dSPaolo Bonzini if (!mon->mux_out) {
1435*6ee7c82dSPaolo Bonzini /* Suspend-resume forces the prompt to be printed. */
1436*6ee7c82dSPaolo Bonzini monitor_suspend(mon);
1437*6ee7c82dSPaolo Bonzini monitor_resume(mon);
1438*6ee7c82dSPaolo Bonzini }
1439*6ee7c82dSPaolo Bonzini qemu_mutex_unlock(&mon->mon_lock);
1440ed7bda5dSKevin Wolf break;
1441ed7bda5dSKevin Wolf
1442ed7bda5dSKevin Wolf case CHR_EVENT_CLOSED:
1443ed7bda5dSKevin Wolf monitor_fdsets_cleanup();
1444ed7bda5dSKevin Wolf break;
14454904ca6aSPhilippe Mathieu-Daudé
14464904ca6aSPhilippe Mathieu-Daudé case CHR_EVENT_BREAK:
14474904ca6aSPhilippe Mathieu-Daudé /* Ignored */
14484904ca6aSPhilippe Mathieu-Daudé break;
1449ed7bda5dSKevin Wolf }
1450ed7bda5dSKevin Wolf }
1451ed7bda5dSKevin Wolf
1452ed7bda5dSKevin Wolf
1453ed7bda5dSKevin Wolf /*
1454ed7bda5dSKevin Wolf * These functions just adapt the readline interface in a typesafe way. We
1455ed7bda5dSKevin Wolf * could cast function pointers but that discards compiler checks.
1456ed7bda5dSKevin Wolf */
monitor_readline_printf(void * opaque,const char * fmt,...)14579edc6313SMarc-André Lureau static void G_GNUC_PRINTF(2, 3) monitor_readline_printf(void *opaque,
1458ed7bda5dSKevin Wolf const char *fmt, ...)
1459ed7bda5dSKevin Wolf {
1460ed7bda5dSKevin Wolf MonitorHMP *mon = opaque;
1461ed7bda5dSKevin Wolf va_list ap;
1462ed7bda5dSKevin Wolf va_start(ap, fmt);
1463ed7bda5dSKevin Wolf monitor_vprintf(&mon->common, fmt, ap);
1464ed7bda5dSKevin Wolf va_end(ap);
1465ed7bda5dSKevin Wolf }
1466ed7bda5dSKevin Wolf
monitor_readline_flush(void * opaque)1467ed7bda5dSKevin Wolf static void monitor_readline_flush(void *opaque)
1468ed7bda5dSKevin Wolf {
1469ed7bda5dSKevin Wolf MonitorHMP *mon = opaque;
1470ed7bda5dSKevin Wolf monitor_flush(&mon->common);
1471ed7bda5dSKevin Wolf }
1472ed7bda5dSKevin Wolf
monitor_init_hmp(Chardev * chr,bool use_readline,Error ** errp)14738e9119a8SKevin Wolf void monitor_init_hmp(Chardev *chr, bool use_readline, Error **errp)
1474ed7bda5dSKevin Wolf {
1475ed7bda5dSKevin Wolf MonitorHMP *mon = g_new0(MonitorHMP, 1);
1476ed7bda5dSKevin Wolf
14778e9119a8SKevin Wolf if (!qemu_chr_fe_init(&mon->common.chr, chr, errp)) {
14788e9119a8SKevin Wolf g_free(mon);
14798e9119a8SKevin Wolf return;
14808e9119a8SKevin Wolf }
14818e9119a8SKevin Wolf
148292082416SKevin Wolf monitor_data_init(&mon->common, false, false, false);
1483ed7bda5dSKevin Wolf
1484fbfc29e3SKevin Wolf mon->use_readline = use_readline;
148592082416SKevin Wolf if (mon->use_readline) {
1486ed7bda5dSKevin Wolf mon->rs = readline_init(monitor_readline_printf,
1487ed7bda5dSKevin Wolf monitor_readline_flush,
1488ed7bda5dSKevin Wolf mon,
1489ed7bda5dSKevin Wolf monitor_find_completion);
1490ed7bda5dSKevin Wolf monitor_read_command(mon, 0);
1491ed7bda5dSKevin Wolf }
1492ed7bda5dSKevin Wolf
1493ed7bda5dSKevin Wolf qemu_chr_fe_set_handlers(&mon->common.chr, monitor_can_read, monitor_read,
1494ed7bda5dSKevin Wolf monitor_event, NULL, &mon->common, NULL, true);
1495ed7bda5dSKevin Wolf monitor_list_append(&mon->common);
1496ed7bda5dSKevin Wolf }
1497