1 /*
2 * Copyright 2009-2017 Citrix Ltd and other contributors
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as published
6 * by the Free Software Foundation; version 2.1 only. with the special
7 * exception on linking described in file LICENSE.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU Lesser General Public License for more details.
13 */
14
15 #include <string.h>
16
17 #include <libxl.h>
18 #include "xl.h"
19
20 struct cmd_spec cmd_table[] = {
21 { "create",
22 &main_create, 1, 1,
23 "Create a domain from config file <filename>",
24 "<ConfigFile> [options] [vars]",
25 "-h Print this help.\n"
26 "-p Leave the domain paused after it is created.\n"
27 "-c Connect to the console after the domain is created.\n"
28 "-f FILE, --defconfig=FILE\n Use the given configuration file.\n"
29 "-q, --quiet Quiet.\n"
30 "-n, --dryrun Dry run - prints the resulting configuration\n"
31 " (deprecated in favour of global -N option).\n"
32 "-d Enable debug messages.\n"
33 "-F Run in foreground until death of the domain.\n"
34 "-e Do not wait in the background for the death of the domain.\n"
35 "-V, --vncviewer Connect to the VNC display after the domain is created.\n"
36 "-A, --vncviewer-autopass\n"
37 " Pass VNC password to viewer via stdin."
38 },
39 { "config-update",
40 &main_config_update, 1, 1,
41 "Update a running domain's saved configuration, used when rebuilding "
42 "the domain after reboot.\n"
43 "WARNING: xl now has better capability to manage domain configuration, "
44 "avoid using this command when possible",
45 "<Domain> <ConfigFile> [options] [vars]",
46 "-h Print this help.\n"
47 "-f FILE, --defconfig=FILE\n Use the given configuration file.\n"
48 "-d Enable debug messages.\n"
49 },
50 { "list",
51 &main_list, 0, 0,
52 "List information about all/some domains",
53 "[options] [Domain]\n",
54 "-l, --long Output all VM details\n"
55 "-v, --verbose Prints out UUIDs and security context\n"
56 "-Z, --context Prints out security context\n"
57 "-c, --cpupool Prints the cpupool the domain is in\n"
58 "-n, --numa Prints out NUMA node affinity"
59 },
60 { "destroy",
61 &main_destroy, 0, 1,
62 "Terminate a domain immediately",
63 "[options] <Domain>\n",
64 "-f Permit destroying domain 0, which will only succeed\n"
65 " when run from disaggregated toolstack domain with a\n"
66 " hardware domain distinct from domain 0."
67 },
68 { "shutdown",
69 &main_shutdown, 0, 1,
70 "Issue a shutdown signal to a domain",
71 "[options] <-a|Domain>",
72 "-a, --all Shutdown all guest domains.\n"
73 "-h Print this help.\n"
74 "-F Fallback to ACPI power event for HVM guests with\n"
75 " no PV drivers.\n"
76 "-w, --wait Wait for guest(s) to shutdown.\n"
77 },
78 { "reboot",
79 &main_reboot, 0, 1,
80 "Issue a reboot signal to a domain",
81 "[options] <-a|Domain>",
82 "-a, --all Shutdown all guest domains.\n"
83 "-h Print this help.\n"
84 "-F Fallback to ACPI reset event for HVM guests with\n"
85 " no PV drivers.\n"
86 "-w, --wait Wait for guest(s) to reboot.\n"
87 },
88 { "pci-attach",
89 &main_pciattach, 0, 1,
90 "Insert a new pass-through pci device",
91 "<Domain> <BDF> [Virtual Slot]",
92 },
93 { "pci-detach",
94 &main_pcidetach, 0, 1,
95 "Remove a domain's pass-through pci device",
96 "<Domain> <BDF>",
97 },
98 { "pci-list",
99 &main_pcilist, 0, 0,
100 "List pass-through pci devices for a domain",
101 "<Domain>",
102 },
103 { "pci-assignable-add",
104 &main_pciassignable_add, 0, 1,
105 "Make a device assignable for pci-passthru",
106 "<BDF>",
107 "-h Print this help.\n"
108 },
109 { "pci-assignable-remove",
110 &main_pciassignable_remove, 0, 1,
111 "Remove a device from being assignable",
112 "[options] <BDF>",
113 "-h Print this help.\n"
114 "-r Attempt to re-assign the device to the\n"
115 " original driver"
116 },
117 { "pci-assignable-list",
118 &main_pciassignable_list, 0, 0,
119 "List all the assignable pci devices",
120 "",
121 },
122 { "pause",
123 &main_pause, 0, 1,
124 "Pause execution of a domain",
125 "<Domain>",
126 },
127 { "unpause",
128 &main_unpause, 0, 1,
129 "Unpause a paused domain",
130 "<Domain>",
131 },
132 { "console",
133 &main_console, 0, 0,
134 "Attach to domain's console",
135 "[options] <Domain>\n"
136 "-t <type> console type, pv , serial or vuart\n"
137 "-n <number> console number"
138 },
139 { "vncviewer",
140 &main_vncviewer, 0, 0,
141 "Attach to domain's VNC server.",
142 "[options] <Domain>\n"
143 "--autopass Pass VNC password to viewer via stdin and\n"
144 " -autopass\n"
145 "--vncviewer-autopass (consistency alias for --autopass)"
146 },
147 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
148 { "save",
149 &main_save, 0, 1,
150 "Save a domain state to restore later",
151 "[options] <Domain> <CheckpointFile> [<ConfigFile>]",
152 "-h Print this help.\n"
153 "-c Leave domain running after creating the snapshot.\n"
154 "-p Leave domain paused after creating the snapshot."
155 },
156 { "migrate",
157 &main_migrate, 0, 1,
158 "Migrate a domain to another host",
159 "[options] <Domain> <host>",
160 "-h Print this help.\n"
161 "-C <config> Send <config> instead of config file from creation.\n"
162 "-s <sshcommand> Use <sshcommand> instead of ssh. String will be passed\n"
163 " to sh. If empty, run <host> instead of ssh <host> xl\n"
164 " migrate-receive [-d -e]\n"
165 "-e Do not wait in the background (on <host>) for the death\n"
166 " of the domain.\n"
167 "--debug Print huge (!) amount of debug during the migration process.\n"
168 "-p Do not unpause domain after migrating it."
169 },
170 { "restore",
171 &main_restore, 0, 1,
172 "Restore a domain from a saved state",
173 "[options] [<ConfigFile>] <CheckpointFile>",
174 "-h Print this help.\n"
175 "-p Do not unpause domain after restoring it.\n"
176 "-e Do not wait in the background for the death of the domain.\n"
177 "-d Enable debug messages.\n"
178 "-V, --vncviewer Connect to the VNC display after the domain is created.\n"
179 "-A, --vncviewer-autopass Pass VNC password to viewer via stdin."
180 },
181 { "migrate-receive",
182 &main_migrate_receive, 0, 1,
183 "Restore a domain from a saved state",
184 "- for internal use only",
185 },
186 #endif
187 { "dump-core",
188 &main_dump_core, 0, 1,
189 "Core dump a domain",
190 "<Domain> <filename>"
191 },
192 { "cd-insert",
193 &main_cd_insert, 1, 1,
194 "Insert a cdrom into a guest's cd drive",
195 "<Domain> <VirtualDevice> <path>",
196 },
197 { "cd-eject",
198 &main_cd_eject, 1, 1,
199 "Eject a cdrom from a guest's cd drive",
200 "<Domain> <VirtualDevice>",
201 },
202 { "mem-max",
203 &main_memmax, 0, 1,
204 "Set the maximum amount reservation for a domain",
205 "<Domain> <MemMB['b'[bytes]|'k'[KB]|'m'[MB]|'g'[GB]|'t'[TB]]>",
206 },
207 { "mem-set",
208 &main_memset, 0, 1,
209 "Set the current memory usage for a domain",
210 "<Domain> <MemMB['b'[bytes]|'k'[KB]|'m'[MB]|'g'[GB]|'t'[TB]]>",
211 },
212 { "button-press",
213 &main_button_press, 0, 1,
214 "Indicate an ACPI button press to the domain",
215 "<Domain> <Button>",
216 "<Button> may be 'power' or 'sleep'."
217 },
218 { "vcpu-list",
219 &main_vcpulist, 0, 0,
220 "List the VCPUs for all/some domains",
221 "[Domain, ...]",
222 },
223 { "vcpu-pin",
224 &main_vcpupin, 1, 1,
225 "Set which CPUs a VCPU can use",
226 "[option] <Domain> <VCPU|all> <Hard affinity|-|all> <Soft affinity|-|all>",
227 "-f, --force undo an override pinning done by the kernel",
228 },
229 { "vcpu-set",
230 &main_vcpuset, 0, 1,
231 "Set the number of active VCPUs allowed for the domain",
232 "[option] <Domain> <vCPUs>",
233 "-i, --ignore-host Don't limit the vCPU based on the host CPU count",
234 },
235 { "vm-list",
236 &main_vm_list, 0, 0,
237 "List guest domains, excluding dom0, stubdoms, etc.",
238 "",
239 },
240 { "info",
241 &main_info, 0, 0,
242 "Get information about Xen host",
243 "-n, --numa List host NUMA topology information",
244 },
245 { "sharing",
246 &main_sharing, 0, 0,
247 "Get information about page sharing",
248 "[Domain]",
249 },
250 { "sched-credit",
251 &main_sched_credit, 0, 1,
252 "Get/set credit scheduler parameters",
253 "[-d <Domain> [-w[=WEIGHT]|-c[=CAP]]] [-s [-t TSLICE] [-r RATELIMIT]] [-p CPUPOOL]",
254 "-d DOMAIN, --domain=DOMAIN Domain to modify\n"
255 "-w WEIGHT, --weight=WEIGHT Weight (int)\n"
256 "-c CAP, --cap=CAP Cap (int)\n"
257 "-s --schedparam Query / modify scheduler parameters\n"
258 "-t TSLICE, --tslice_ms=TSLICE Set the timeslice, in milliseconds\n"
259 "-r RLIMIT, --ratelimit_us=RLIMIT Set the scheduling rate limit, in microseconds\n"
260 "-p CPUPOOL, --cpupool=CPUPOOL Restrict output to CPUPOOL"
261 },
262 { "sched-credit2",
263 &main_sched_credit2, 0, 1,
264 "Get/set credit2 scheduler parameters",
265 "[-d <Domain> [-w[=WEIGHT]]] [-p CPUPOOL]",
266 "-d DOMAIN, --domain=DOMAIN Domain to modify\n"
267 "-w WEIGHT, --weight=WEIGHT Weight (int)\n"
268 "-c CAP, --cap=CAP Cap (int)\n"
269 "-s --schedparam Query / modify scheduler parameters\n"
270 "-r RLIMIT, --ratelimit_us=RLIMIT Set the scheduling rate limit, in microseconds\n"
271 "-p CPUPOOL, --cpupool=CPUPOOL Restrict output to CPUPOOL"
272 },
273 { "sched-rtds",
274 &main_sched_rtds, 0, 1,
275 "Get/set rtds scheduler parameters",
276 "[-d <Domain> [-v[=VCPUID/all]] [-p[=PERIOD]] [-b[=BUDGET]] [-e[=Extratime]]]",
277 "-d DOMAIN, --domain=DOMAIN Domain to modify\n"
278 "-v VCPUID/all, --vcpuid=VCPUID/all VCPU to modify or output;\n"
279 " Using '-v all' to modify/output all vcpus\n"
280 "-p PERIOD, --period=PERIOD Period (us)\n"
281 "-b BUDGET, --budget=BUDGET Budget (us)\n"
282 "-e Extratime, --extratime=Extratime Extratime (1=yes, 0=no)\n"
283 },
284 { "domid",
285 &main_domid, 0, 0,
286 "Convert a domain name to domain id",
287 "<DomainName>",
288 },
289 { "domname",
290 &main_domname, 0, 0,
291 "Convert a domain id to domain name",
292 "<DomainId>",
293 },
294 { "rename",
295 &main_rename, 0, 1,
296 "Rename a domain",
297 "<Domain> <NewDomainName>",
298 },
299 { "trigger",
300 &main_trigger, 0, 1,
301 "Send a trigger to a domain",
302 "<Domain> <nmi|reset|init|power|sleep|s3resume> [<VCPU>]",
303 },
304 { "sysrq",
305 &main_sysrq, 0, 1,
306 "Send a sysrq to a domain",
307 "<Domain> <letter>",
308 },
309 { "debug-keys",
310 &main_debug_keys, 0, 1,
311 "Send debug keys to Xen",
312 "<Keys>",
313 },
314 { "set-parameters",
315 &main_set_parameters, 0, 1,
316 "Set hypervisor parameters",
317 "<Params>",
318 },
319 { "dmesg",
320 &main_dmesg, 0, 0,
321 "Read and/or clear dmesg buffer",
322 "[-c]",
323 " -c Clear dmesg buffer as well as printing it",
324 },
325 { "top",
326 &main_top, 0, 0,
327 "Monitor a host and the domains in real time",
328 "",
329 },
330 { "network-attach",
331 &main_networkattach, 1, 1,
332 "Create a new virtual network device",
333 "<Domain> [type=<type>] [mac=<mac>] [bridge=<bridge>] "
334 "[ip=<ip>] [script=<script>] [backend=<BackDomain>] [vifname=<name>] "
335 "[rate=<rate>] [model=<model>] [accel=<accel>]",
336 },
337 { "network-list",
338 &main_networklist, 0, 0,
339 "List virtual network interfaces for a domain",
340 "<Domain(s)>",
341 },
342 { "network-detach",
343 &main_networkdetach, 0, 1,
344 "Destroy a domain's virtual network device",
345 "<Domain> <DevId|mac>",
346 },
347 { "channel-list",
348 &main_channellist, 0, 0,
349 "List virtual channel devices for a domain",
350 "<Domain(s)>",
351 },
352 { "block-attach",
353 &main_blockattach, 1, 1,
354 "Create a new virtual block device",
355 "<Domain> <disk-spec-component(s)>...",
356 },
357 { "block-list",
358 &main_blocklist, 0, 0,
359 "List virtual block devices for a domain",
360 "<Domain(s)>",
361 },
362 { "block-detach",
363 &main_blockdetach, 0, 1,
364 "Destroy a domain's virtual block device",
365 "<Domain> <DevId>",
366 },
367 { "vtpm-attach",
368 &main_vtpmattach, 1, 1,
369 "Create a new virtual TPM device",
370 "<Domain> [uuid=<uuid>] [backend=<BackDomain>]",
371 },
372 { "vtpm-list",
373 &main_vtpmlist, 0, 0,
374 "List virtual TPM devices for a domain",
375 "<Domain(s)>",
376 },
377 { "vtpm-detach",
378 &main_vtpmdetach, 0, 1,
379 "Destroy a domain's virtual TPM device",
380 "<Domain> <DevId|uuid>",
381 },
382 { "vdispl-attach",
383 &main_vdisplattach, 1, 1,
384 "Create a new virtual display device",
385 "<Domain> [backend=<BackDomain>] [be-alloc=<BackAlloc>] [connectors='<Connectors>']",
386 " BackAlloc - set to 1 to if backend allocates display buffers\n"
387 " Connectors - list of connector's description in ID:WxH format,\n"
388 " where: ID - unique connector ID, W - connector width,\n"
389 " H - connector height: connectors='id0:800x600;id1:1024x768'\n"
390 },
391 { "vdispl-list",
392 &main_vdispllist, 0, 0,
393 "List virtual display devices for a domain",
394 "<Domain(s)>",
395 },
396 { "vdispl-detach",
397 &main_vdispldetach, 0, 1,
398 "Destroy a domain's virtual display device",
399 "<Domain> <DevId>",
400 },
401 { "uptime",
402 &main_uptime, 0, 0,
403 "Print uptime for all/some domains",
404 "[-s] [Domain]",
405 },
406 { "claims",
407 &main_claims, 0, 0,
408 "List outstanding claim information about all domains",
409 "",
410 "",
411 },
412 { "tmem-list",
413 &main_tmem_list, 0, 0,
414 "List tmem pools",
415 "[-l] [<Domain>|-a]",
416 " -l List tmem stats",
417 },
418 { "tmem-freeze",
419 &main_tmem_freeze, 0, 1,
420 "Freeze tmem pools",
421 "[<Domain>|-a]",
422 " -a Freeze all tmem",
423 },
424 { "tmem-thaw",
425 &main_tmem_thaw, 0, 1,
426 "Thaw tmem pools",
427 "[<Domain>|-a]",
428 " -a Thaw all tmem",
429 },
430 { "tmem-set",
431 &main_tmem_set, 0, 1,
432 "Change tmem settings",
433 "[<Domain>|-a] [-w[=WEIGHT]|-c[=CAP]|-p[=COMPRESS]]",
434 " -a Operate on all tmem\n"
435 " -w WEIGHT Weight (int)\n"
436 " -p COMPRESS Compress (int)",
437 },
438 { "tmem-shared-auth",
439 &main_tmem_shared_auth, 0, 1,
440 "De/authenticate shared tmem pool",
441 "[<Domain>|-a] [-u[=UUID] [-A[=AUTH]",
442 " -a Authenticate for all tmem pools\n"
443 " -u UUID Specify uuid\n"
444 " (abcdef01-2345-6789-1234-567890abcdef)\n"
445 " -A AUTH 0=deauth,1=auth",
446 },
447 { "tmem-freeable",
448 &main_tmem_freeable, 0, 0,
449 "Get information about how much freeable memory (MB) is in-use by tmem",
450 "",
451 },
452 { "cpupool-create",
453 &main_cpupoolcreate, 1, 1,
454 "Create a new CPU pool",
455 "[options] [<ConfigFile>] [Variable=value ...]",
456 "-h, --help Print this help.\n"
457 "-f FILE, --defconfig=FILE Use the given configuration file.\n"
458 "-n, --dryrun Dry run - prints the resulting configuration.\n"
459 " (deprecated in favour of global -N option).\n"
460 "\nSee the xlcpupool.cfg(5) manpage for more information.",
461
462 },
463 { "cpupool-list",
464 &main_cpupoollist, 0, 0,
465 "List CPU pools on host",
466 "[-c|--cpus] [<CPU Pool>]",
467 "-c, --cpus Output list of CPUs used by a pool"
468 },
469 { "cpupool-destroy",
470 &main_cpupooldestroy, 0, 1,
471 "Deactivates a CPU pool",
472 "<CPU Pool>",
473 },
474 { "cpupool-rename",
475 &main_cpupoolrename, 0, 1,
476 "Renames a CPU pool",
477 "<CPU Pool> <new name>",
478 },
479 { "cpupool-cpu-add",
480 &main_cpupoolcpuadd, 0, 1,
481 "Adds a CPU to a CPU pool",
482 "<CPU Pool> <CPU nr>|node:<node nr>",
483 },
484 { "cpupool-cpu-remove",
485 &main_cpupoolcpuremove, 0, 1,
486 "Removes a CPU from a CPU pool",
487 "<CPU Pool> <CPU nr>|node:<node nr>",
488 },
489 { "cpupool-migrate",
490 &main_cpupoolmigrate, 0, 1,
491 "Moves a domain into a CPU pool",
492 "<Domain> <CPU Pool>",
493 },
494 { "cpupool-numa-split",
495 &main_cpupoolnumasplit, 0, 1,
496 "Splits up the machine into one CPU pool per NUMA node",
497 "",
498 },
499 { "getenforce",
500 &main_getenforce, 0, 0,
501 "Returns the current enforcing mode of the Flask Xen security module",
502 "",
503 },
504 { "setenforce",
505 &main_setenforce, 0, 1,
506 "Sets the current enforcing mode of the Flask Xen security module",
507 "<1|0|Enforcing|Permissive>",
508 },
509 { "loadpolicy",
510 &main_loadpolicy, 0, 1,
511 "Loads a new policy int the Flask Xen security module",
512 "<policy file>",
513 },
514 #ifndef LIBXL_HAVE_NO_SUSPEND_RESUME
515 { "remus",
516 &main_remus, 0, 1,
517 "Enable Remus HA for domain",
518 "[options] <Domain> [<host>]",
519 "-i MS Checkpoint domain memory every MS milliseconds (def. 200ms).\n"
520 "-u Disable memory checkpoint compression.\n"
521 "-s <sshcommand> Use <sshcommand> instead of ssh. String will be passed\n"
522 " to sh. If empty, run <host> instead of \n"
523 " ssh <host> xl migrate-receive -r [-e]\n"
524 "-e Do not wait in the background (on <host>) for the death\n"
525 " of the domain.\n"
526 "-N <netbufscript> Use netbufscript to setup network buffering instead of the\n"
527 " default script (/etc/xen/scripts/remus-netbuf-setup).\n"
528 "-F Enable unsafe configurations [-b|-n|-d flags]. Use this option\n"
529 " with caution as failover may not work as intended.\n"
530 "-b Replicate memory checkpoints to /dev/null (blackhole).\n"
531 " Works only in unsafe mode.\n"
532 "-n Disable network output buffering. Works only in unsafe mode.\n"
533 "-d Disable disk replication. Works only in unsafe mode.\n"
534 "-c Enable COLO HA. It is conflict with -i and -b, and memory\n"
535 " checkpoint must be disabled.\n"
536 "-p Use COLO userspace proxy."
537 },
538 #endif
539 { "devd",
540 &main_devd, 0, 1,
541 "Daemon that listens for devices and launches backends",
542 "[options]",
543 "-F Run in the foreground.\n"
544 "-p, --pidfile [FILE] Write PID to pidfile when daemonizing.",
545 },
546 #if defined(__i386__) || defined(__x86_64__)
547 { "psr-hwinfo",
548 &main_psr_hwinfo, 0, 1,
549 "Show hardware information for Platform Shared Resource",
550 "[options]",
551 "-m, --cmt Show Cache Monitoring Technology (CMT) hardware info\n"
552 "-a, --cat Show Cache Allocation Technology (CAT) hardware info\n"
553 },
554 { "psr-cmt-attach",
555 &main_psr_cmt_attach, 0, 1,
556 "Attach Cache Monitoring Technology service to a domain",
557 "<Domain>",
558 },
559 { "psr-cmt-detach",
560 &main_psr_cmt_detach, 0, 1,
561 "Detach Cache Monitoring Technology service from a domain",
562 "<Domain>",
563 },
564 { "psr-cmt-show",
565 &main_psr_cmt_show, 0, 1,
566 "Show Cache Monitoring Technology information",
567 "<PSR-CMT-Type> <Domain>",
568 "Available monitor types:\n"
569 "\"cache-occupancy\": Show L3 cache occupancy(KB)\n"
570 "\"total-mem-bandwidth\": Show total memory bandwidth(KB/s)\n"
571 "\"local-mem-bandwidth\": Show local memory bandwidth(KB/s)\n",
572 },
573 { "psr-cat-set",
574 &main_psr_cat_cbm_set, 0, 1,
575 "Set cache capacity bitmasks(CBM) for a domain",
576 "[options] <Domain> <CBM>",
577 "-s <socket> Specify the socket to process, otherwise all sockets are processed\n"
578 "-l <level> Specify the cache level to process, otherwise L3 cache is processed\n"
579 "-c Set code CBM if CDP is supported\n"
580 "-d Set data CBM if CDP is supported\n"
581 },
582 { "psr-cat-show",
583 &main_psr_cat_show, 0, 1,
584 "Show Cache Allocation Technology information",
585 "[options] <Domain>",
586 "-l <level> Specify the cache level to process, otherwise L3 cache is processed\n"
587 },
588 #endif
589 { "usbctrl-attach",
590 &main_usbctrl_attach, 0, 1,
591 "Create a virtual USB controller for a domain",
592 "<Domain> [type=pv] [version=<version>] [ports=<number>]",
593 },
594 { "usbctrl-detach",
595 &main_usbctrl_detach, 0, 1,
596 "Remove the virtual USB controller specified by <DevId> for a domain",
597 "<Domain> <DevId>",
598 },
599 { "usbdev-attach",
600 &main_usbdev_attach, 0, 1,
601 "Attach a USB device to a domain",
602 "<Domain> hostbus=<busnum> hostaddr=<devnum> [controller=<DevId> [port=<port>]]",
603 },
604 { "usbdev-detach",
605 &main_usbdev_detach, 0, 1,
606 "Detach a USB device from a domain",
607 "<Domain> <controller> <port>",
608 },
609 { "usb-list",
610 &main_usblist, 0, 0,
611 "List information about all USB controllers and devices for a domain",
612 "<Domain>",
613 },
614 { "qemu-monitor-command",
615 &main_qemu_monitor_command, 0, 1,
616 "Issue a qemu monitor command to the device model of a domain",
617 "<Domain> <Command>",
618 },
619 };
620
621 int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);
622
623 /* Look up a command in the table, allowing unambiguous truncation */
cmdtable_lookup(const char * s)624 struct cmd_spec *cmdtable_lookup(const char *s)
625 {
626 struct cmd_spec *cmd = NULL;
627 size_t len;
628 int i, count = 0;
629
630 if (!s)
631 return NULL;
632 len = strlen(s);
633 for (i = 0; i < cmdtable_len; i++) {
634 if (!strncmp(s, cmd_table[i].cmd_name, len)) {
635 cmd = &cmd_table[i];
636 /* Take an exact match, even if it also prefixes another command */
637 if (len == strlen(cmd->cmd_name))
638 return cmd;
639 count++;
640 }
641 }
642 return (count == 1) ? cmd : NULL;
643 }
644
645 /*
646 * Local variables:
647 * mode: C
648 * c-basic-offset: 4
649 * indent-tabs-mode: nil
650 * End:
651 */
652