xref: /qemu/chardev/char-hmp-cmds.c (revision f969c627)
1 /*
2  * HMP commands related to character devices
3  *
4  * Copyright IBM, Corp. 2011
5  *
6  * Authors:
7  *  Anthony Liguori   <aliguori@us.ibm.com>
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2.  See
10  * the COPYING file in the top-level directory.
11  *
12  * Contributions after 2012-01-13 are licensed under the terms of the
13  * GNU GPL, version 2 or (at your option) any later version.
14  */
15 
16 #include "qemu/osdep.h"
17 #include "chardev/char.h"
18 #include "monitor/hmp.h"
19 #include "monitor/monitor.h"
20 #include "qapi/error.h"
21 #include "qapi/qapi-commands-char.h"
22 #include "qapi/qmp/qdict.h"
23 #include "qemu/config-file.h"
24 #include "qemu/option.h"
25 
26 void hmp_info_chardev(Monitor *mon, const QDict *qdict)
27 {
28     ChardevInfoList *char_info, *info;
29 
30     char_info = qmp_query_chardev(NULL);
31     for (info = char_info; info; info = info->next) {
32         monitor_printf(mon, "%s: filename=%s\n", info->value->label,
33                                                  info->value->filename);
34     }
35 
36     qapi_free_ChardevInfoList(char_info);
37 }
38 
39 void hmp_ringbuf_write(Monitor *mon, const QDict *qdict)
40 {
41     const char *chardev = qdict_get_str(qdict, "device");
42     const char *data = qdict_get_str(qdict, "data");
43     Error *err = NULL;
44 
45     qmp_ringbuf_write(chardev, data, false, 0, &err);
46 
47     hmp_handle_error(mon, err);
48 }
49 
50 void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
51 {
52     uint32_t size = qdict_get_int(qdict, "size");
53     const char *chardev = qdict_get_str(qdict, "device");
54     char *data;
55     Error *err = NULL;
56     int i;
57 
58     data = qmp_ringbuf_read(chardev, size, false, 0, &err);
59     if (hmp_handle_error(mon, err)) {
60         return;
61     }
62 
63     for (i = 0; data[i]; i++) {
64         unsigned char ch = data[i];
65 
66         if (ch == '\\') {
67             monitor_printf(mon, "\\\\");
68         } else if ((ch < 0x20 && ch != '\n' && ch != '\t') || ch == 0x7F) {
69             monitor_printf(mon, "\\u%04X", ch);
70         } else {
71             monitor_printf(mon, "%c", ch);
72         }
73 
74     }
75     monitor_printf(mon, "\n");
76     g_free(data);
77 }
78 
79 void hmp_chardev_add(Monitor *mon, const QDict *qdict)
80 {
81     const char *args = qdict_get_str(qdict, "args");
82     Error *err = NULL;
83     QemuOpts *opts;
84 
85     opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), args, true);
86     if (opts == NULL) {
87         error_setg(&err, "Parsing chardev args failed");
88     } else {
89         qemu_chr_new_from_opts(opts, NULL, &err);
90         qemu_opts_del(opts);
91     }
92     hmp_handle_error(mon, err);
93 }
94 
95 void hmp_chardev_change(Monitor *mon, const QDict *qdict)
96 {
97     const char *args = qdict_get_str(qdict, "args");
98     const char *id;
99     Error *err = NULL;
100     ChardevBackend *backend = NULL;
101     ChardevReturn *ret = NULL;
102     QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), args,
103                                              true);
104     if (!opts) {
105         error_setg(&err, "Parsing chardev args failed");
106         goto end;
107     }
108 
109     id = qdict_get_str(qdict, "id");
110     if (qemu_opts_id(opts)) {
111         error_setg(&err, "Unexpected 'id' parameter");
112         goto end;
113     }
114 
115     backend = qemu_chr_parse_opts(opts, &err);
116     if (!backend) {
117         goto end;
118     }
119 
120     ret = qmp_chardev_change(id, backend, &err);
121 
122 end:
123     qapi_free_ChardevReturn(ret);
124     qapi_free_ChardevBackend(backend);
125     qemu_opts_del(opts);
126     hmp_handle_error(mon, err);
127 }
128 
129 void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
130 {
131     Error *local_err = NULL;
132 
133     qmp_chardev_remove(qdict_get_str(qdict, "id"), &local_err);
134     hmp_handle_error(mon, local_err);
135 }
136 
137 void hmp_chardev_send_break(Monitor *mon, const QDict *qdict)
138 {
139     Error *local_err = NULL;
140 
141     qmp_chardev_send_break(qdict_get_str(qdict, "id"), &local_err);
142     hmp_handle_error(mon, local_err);
143 }
144 
145 void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str)
146 {
147     size_t len;
148     ChardevBackendInfoList *list, *start;
149 
150     if (nb_args != 2) {
151         return;
152     }
153     len = strlen(str);
154     readline_set_completion_index(rs, len);
155 
156     start = list = qmp_query_chardev_backends(NULL);
157     while (list) {
158         const char *chr_name = list->value->name;
159 
160         if (!strncmp(chr_name, str, len)) {
161             readline_add_completion(rs, chr_name);
162         }
163         list = list->next;
164     }
165     qapi_free_ChardevBackendInfoList(start);
166 }
167 
168 void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str)
169 {
170     size_t len;
171     ChardevInfoList *list, *start;
172 
173     if (nb_args != 2) {
174         return;
175     }
176     len = strlen(str);
177     readline_set_completion_index(rs, len);
178 
179     start = list = qmp_query_chardev(NULL);
180     while (list) {
181         ChardevInfo *chr = list->value;
182 
183         if (!strncmp(chr->label, str, len)) {
184             readline_add_completion(rs, chr->label);
185         }
186         list = list->next;
187     }
188     qapi_free_ChardevInfoList(start);
189 }
190 
191 static void ringbuf_completion(ReadLineState *rs, const char *str)
192 {
193     size_t len;
194     ChardevInfoList *list, *start;
195 
196     len = strlen(str);
197     readline_set_completion_index(rs, len);
198 
199     start = list = qmp_query_chardev(NULL);
200     while (list) {
201         ChardevInfo *chr_info = list->value;
202 
203         if (!strncmp(chr_info->label, str, len)) {
204             Chardev *chr = qemu_chr_find(chr_info->label);
205             if (chr && CHARDEV_IS_RINGBUF(chr)) {
206                 readline_add_completion(rs, chr_info->label);
207             }
208         }
209         list = list->next;
210     }
211     qapi_free_ChardevInfoList(start);
212 }
213 
214 void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str)
215 {
216     if (nb_args != 2) {
217         return;
218     }
219     ringbuf_completion(rs, str);
220 }
221