* tools/virsh.c (cmdEcho): New command.
(commands): Add it.
(vshCmdOptType): Add VSH_OT_ARGV.
(vshCmddefGetData): Special case new opt flag.
(vshCommandOptArgv): New function.
---
Not complete yet, but this shows what I'm thinking of. Adding the
echo command has two benefits:
1. It will let me add unit tests for the recent virsh command line
improvements - echo back arbitrary strings to make sure quoting is as
desired. This part works with what I have here, before I ran out of
time to finish this today.
2. Make it easier for a user on the command line to conver an
arbitrary string into something safe for shell evalution and/or XML
usage, by munging the input in a way that it can be reused in the
desired context. Not yet implemented; hence the RFC.
It exploits the fact that -- is consumed as the end-of-options,
hence, there is no way for to be recognized as a valid option
name, so the only way we can encounter VSH_OT_ARGV is via the
new argv handling, at which point we can handle all remaining
command line arguments.
tools/virsh.c | 88 +++-
1 files changed, 80 insertions(+), 8 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index 89c2e1e..f361658 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -119,11 +119,12 @@ typedef enum {
* vshCmdOptType - command option type
*/
typedef enum {
-VSH_OT_NONE = 0,/* none */
-VSH_OT_BOOL,/* boolean option */
-VSH_OT_STRING, /* string option */
-VSH_OT_INT, /* int option */
-VSH_OT_DATA /* string data (as non-option) */
+VSH_OT_NONE = 0, /* none */
+VSH_OT_BOOL, /* boolean option */
+VSH_OT_STRING, /* string option */
+VSH_OT_INT, /* int option */
+VSH_OT_DATA, /* string data (as non-option) */
+VSH_OT_ARGV /* remaining arguments, opt-name should be */
} vshCmdOptType;
/*
@@ -230,6 +231,7 @@ static char *vshCommandOptString(const vshCmd *cmd, const
char *name,
static long long vshCommandOptLongLong(const vshCmd *cmd, const char *name,
int *found);
static int vshCommandOptBool(const vshCmd *cmd, const char *name);
+static char *vshCommandOptArgv(const vshCmd *cmd, int count);
#define VSH_BYID (1 1)
#define VSH_BYUUID (1 2)
@@ -8917,6 +8919,54 @@ cmdPwd(vshControl *ctl, const vshCmd *cmd
ATTRIBUTE_UNUSED)
#endif
/*
+ * echo command
+ */
+static const vshCmdInfo info_echo[] = {
+{help, N_(echo arguments)},
+{desc, N_(Echo back arguments, possibly with quoting.)},
+{NULL, NULL}
+};
+
+static const vshCmdOptDef opts_echo[] = {
+{shell, VSH_OT_BOOL, 0, N_(escape for shell use)},
+{xml, VSH_OT_BOOL, 0, N_(escape for XML use)},
+{, VSH_OT_ARGV, 0, N_(arguments to echo)},
+{NULL, 0, 0, NULL}
+};
+
+/* Exists mainly for debugging virsh, but also handy for adding back
+ * quotes for later evaluation.
+ */
+static int
+cmdEcho (vshControl *ctl ATTRIBUTE_UNUSED, const vshCmd *cmd)
+{
+bool shell = false;
+bool xml = false;
+int count = 0;
+char *arg;
+virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+if (vshCommandOptBool(cmd, shell))
+shell = true;
+if (vshCommandOptBool(cmd, xml))
+xml = true;
+
+while ((arg = vshCommandOptArgv(cmd, count)) != NULL) {
+/* TODO - use buf */
+if (xml) {
+/* TODO - use virBufferEscapeString */
+}
+if (shell) {
+/* TODO - add '' and escape embedded ' */
+}
+vshPrint(ctl, %s%s, count ? : , arg);
+count++;
+}
+
+return TRUE;
+}
+
+/*
* edit command
*/
static const vshCmdInfo info_edit[] = {
@@ -9545,6 +9595,7 @@ static const vshCmdDef commands[] = {
{domxml-from-native, cmdDomXMLFromNative, opts_domxmlfromnative,
info_domxmlfromnative},
{domxml-to-native, cmdDomXMLToNative, opts_domxmltonative,
info_domxmltonative},
{dumpxml, cmdDumpXML, opts_dumpxml, info_dumpxml},
+{echo, cmdEcho, opts_echo, info_echo},
{edit, cmdEdit, opts_edit, info_edit},
{find-storage-pool-sources, cmdPoolDiscoverSources,
opts_find_storage_pool_sources, info_find_storage_pool_sources},
@@ -9707,8 +9758,8 @@ vshCmddefGetData(const vshCmdDef * cmd, int data_ct)
const vshCmdOptDef *opt;
for (opt = cmd-opts; opt opt-name; opt++) {
-if (opt-type == VSH_OT_DATA) {
-if (data_ct == 0)
+if (opt-type = VSH_OT_DATA) {
+if (data_ct == 0 || opt-type == VSH_OT_ARGV)
return opt;
else
data_ct--;
@@ -9970,6 +10021,27 @@ vshCommandOptBool(const vshCmd *cmd, const char *name)
return vshCommandOpt(cmd, name) ? TRUE : FALSE;
}
+/*
+ * Returns the COUNT argv argument, or NULL after last argument.
+ *
+ * Requires that a VSH_OT_ARGV option with the name be last in the
+ * list of supported options in CMD-def-opts.
+ */
+static