xref: /qemu/monitor/hmp.c (revision 164dafd1)
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, &reg, 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