The GOptionContext API has the benefit over getopt_long that it will
automatically handle --help output formatting.
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
---
tools/virsh.c | 303 ++++++++++++++++++++++----------------------------
1 file changed, 135 insertions(+), 168 deletions(-)
diff --git a/tools/virsh.c b/tools/virsh.c
index ec20f35a77..6c469ff576 100644
--- a/tools/virsh.c
+++ b/tools/virsh.c
@@ -23,7 +23,6 @@
#include <stdarg.h>
#include <unistd.h>
-#include <getopt.h>
#include <sys/time.h>
#include <fcntl.h>
#include <time.h>
@@ -445,53 +444,36 @@ virshDeinit(vshControl *ctl)
}
/*
- * Print usage
+ * Build help description for commands
*/
-static void
-virshUsage(void)
+static char *
+virshBuildDescription(void)
{
const vshCmdGrp *grp;
const vshCmdDef *cmd;
-
- fprintf(stdout, _("\n%s [options]... [<command_string>]"
- "\n%s [options]... <command> [args...]\n\n"
- " options:\n"
- " -c | --connect=URI hypervisor connection URI\n"
- " -d | --debug=NUM debug level [0-4]\n"
- " -e | --escape <char> set escape sequence for console\n"
- " -h | --help this help\n"
- " -k | --keepalive-interval=NUM\n"
- " keepalive interval in seconds, 0 for disable\n"
- " -K | --keepalive-count=NUM\n"
- " number of possible missed keepalive messages\n"
- " -l | --log=FILE output logging to file\n"
- " -q | --quiet quiet mode\n"
- " -r | --readonly connect readonly\n"
- " -t | --timing print timing information\n"
- " -v short version\n"
- " -V long version\n"
- " --version[=TYPE] version, TYPE is short or long (default short)\n"
- " commands (non interactive mode):\n\n"), progname,
- progname);
+ GString *str = g_string_new("Commands (non interactive mode):\n\n");
for (grp = cmdGroups; grp->name; grp++) {
- fprintf(stdout, _(" %s (help keyword '%s')\n"),
- grp->name, grp->keyword);
+ g_string_append_printf(str,
+ _(" %s (help keyword '%s')\n"),
+ grp->name, grp->keyword);
for (cmd = grp->commands; cmd->name; cmd++) {
if (cmd->flags & VSH_CMD_FLAG_ALIAS)
continue;
- fprintf(stdout,
- " %-30s %s\n", cmd->name,
- _(vshCmddefGetInfo(cmd, "help")));
+ g_string_append_printf(str,
+ " %-30s %s\n",
+ cmd->name,
+ _(vshCmddefGetInfo(cmd, "help")));
}
- fprintf(stdout, "\n");
+ g_string_append_printf(str, "\n");
}
- fprintf(stdout, "%s",
- _("\n (specify help <group> for details about the commands in the group)\n"));
- fprintf(stdout, "%s",
- _("\n (specify help <command> for details about the command)\n\n"));
- return;
+ g_string_append_printf(str,
+ _("Specify help <group> for details about the commands in the group)\n"));
+ g_string_append_printf(str,
+ _("Specify help <command> for details about the command)\n"));
+
+ return g_string_free(str, FALSE);
}
/*
@@ -647,6 +629,22 @@ virshAllowedEscapeChar(char c)
('@' <= c && c <= '_');
}
+static gboolean
+virshVersion(const gchar *option_name G_GNUC_UNUSED,
+ const gchar *value,
+ gpointer data,
+ GError **error G_GNUC_UNUSED)
+{
+ vshControl *ctl = data;
+
+ if (value == NULL || STRNEQ(value, "long"))
+ puts(VERSION);
+ else
+ virshShowVersion(ctl);
+
+ exit(EXIT_SUCCESS);
+}
+
/*
* argv[]: virsh [options] [command]
*
@@ -654,152 +652,121 @@ virshAllowedEscapeChar(char c)
static bool
virshParseArgv(vshControl *ctl, int argc, char **argv)
{
- int arg, len, debug, keepalive;
- size_t i;
- int longindex = -1;
+ int debug = 0;
+ bool version = false;
+ size_t len;
virshControlPtr priv = ctl->privData;
- struct option opt[] = {
- {"connect", required_argument, NULL, 'c'},
- {"debug", required_argument, NULL, 'd'},
- {"escape", required_argument, NULL, 'e'},
- {"help", no_argument, NULL, 'h'},
- {"keepalive-interval", required_argument, NULL, 'k'},
- {"keepalive-count", required_argument, NULL, 'K'},
- {"log", required_argument, NULL, 'l'},
- {"quiet", no_argument, NULL, 'q'},
- {"readonly", no_argument, NULL, 'r'},
- {"timing", no_argument, NULL, 't'},
- {"version", optional_argument, NULL, 'v'},
- {NULL, 0, NULL, 0}
+ char *logfile = NULL;
+ int keepalive_interval = INT_MAX;
+ int keepalive_count = INT_MAX;
+ GOptionEntry opt[] = {
+ { "connect", 'c', 0,
+ G_OPTION_ARG_STRING, &ctl->connname,
+ _("hypervisor connection URI"), "URI" },
+ { "debug", 'd', 0,
+ G_OPTION_ARG_INT, &debug,
+ _("debug level [0-4]\n"), "LEVEL" },
+ { "escape", 'e', 0,
+ G_OPTION_ARG_STRING, &priv->escapeChar,
+ _("set escape sequence for console"), "ESCAPE" },
+ { "keepalive-interval", 'k', 0,
+ G_OPTION_ARG_INT, &keepalive_interval,
+ _("keepalive interval in seconds, 0 for disable"), "SECS" },
+ { "keepalive-count", 'K', 0,
+ G_OPTION_ARG_INT, &keepalive_count,
+ _("number of possible missed keepalive messages"), "NUM" },
+ { "log", 'l', 0,
+ G_OPTION_ARG_STRING, &logfile,
+ _("output logging to file"), "FILENAME" },
+ { "quiet", 'q', 0,
+ G_OPTION_ARG_NONE, &ctl->quiet,
+ _("quite mode"), NULL },
+ { "readonly", 'r', 0,
+ G_OPTION_ARG_NONE, &priv->readonly,
+ _("connect readonly"), NULL },
+ { "timing", 't', 0,
+ G_OPTION_ARG_NONE, &ctl->timing,
+ _("print timing information"), NULL },
+ { "version", 'v', G_OPTION_FLAG_OPTIONAL_ARG,
+ G_OPTION_ARG_CALLBACK, virshVersion,
+ _("print short version"), "[short]" },
+ { "version", 'V', 0,
+ G_OPTION_ARG_NONE, &version,
+ _("print long version"), "long" },
+ { NULL, 0, 0, 0, NULL, NULL, NULL },
};
+ g_autoptr(GOptionContext) optctx = NULL;
+ GOptionGroup *optgrp;
+ g_autoptr(GError) error = NULL;
+
+ optctx = g_option_context_new(_("[COMMAND [OPTION…] - libvirt shell"));
+ optgrp = g_option_group_new(NULL, NULL, NULL, ctl, NULL);
+ g_option_group_set_translation_domain(optgrp, PACKAGE);
+ g_option_group_add_entries(optgrp, opt);
+ g_option_context_set_main_group(optctx, optgrp);
+ g_option_context_set_strict_posix(optctx, true);
+ g_option_context_set_description(optctx,
+ virshBuildDescription());
+
+ if (!g_option_context_parse(optctx, &argc, &argv, &error)) {
+ vshError(ctl, _("option parsing failed: %s\n"), error->message);
+ exit(EXIT_FAILURE);
+ }
- /* Standard (non-command) options. The leading + ensures that no
- * argument reordering takes place, so that command options are
- * not confused with top-level virsh options. */
- while ((arg = getopt_long(argc, argv, "+:c:d:e:hk:K:l:qrtvV", opt, &longindex)) != -1) {
- switch (arg) {
- case 'c':
- VIR_FREE(ctl->connname);
- ctl->connname = vshStrdup(ctl, optarg);
- break;
- case 'd':
- if (virStrToLong_i(optarg, NULL, 10, &debug) < 0) {
- vshError(ctl, _("option %s takes a numeric argument"),
- longindex == -1 ? "-d" : "--debug");
- exit(EXIT_FAILURE);
- }
- if (debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR)
- vshError(ctl, _("ignoring debug level %d out of range [%d-%d]"),
- debug, VSH_ERR_DEBUG, VSH_ERR_ERROR);
- else
- ctl->debug = debug;
- break;
- case 'e':
- len = strlen(optarg);
-
- if ((len == 2 && *optarg == '^' &&
- virshAllowedEscapeChar(optarg[1])) ||
- (len == 1 && *optarg != '^')) {
- priv->escapeChar = optarg;
- } else {
- vshError(ctl, _("Invalid string '%s' for escape sequence"),
- optarg);
- exit(EXIT_FAILURE);
- }
- break;
- case 'h':
- virshUsage();
- exit(EXIT_SUCCESS);
- break;
- case 'k':
- if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0) {
- vshError(ctl,
- _("Invalid value for option %s"),
- longindex == -1 ? "-k" : "--keepalive-interval");
- exit(EXIT_FAILURE);
- }
-
- if (keepalive < 0) {
- vshError(ctl,
- _("option %s requires a positive integer argument"),
- longindex == -1 ? "-k" : "--keepalive-interval");
- exit(EXIT_FAILURE);
- }
- ctl->keepalive_interval = keepalive;
- break;
- case 'K':
- if (virStrToLong_i(optarg, NULL, 0, &keepalive) < 0) {
- vshError(ctl,
- _("Invalid value for option %s"),
- longindex == -1 ? "-K" : "--keepalive-count");
- exit(EXIT_FAILURE);
- }
+ if (debug < VSH_ERR_DEBUG || debug > VSH_ERR_ERROR) {
+ vshError(ctl, _("debug level %d out of range [%d-%d]"),
+ debug, VSH_ERR_DEBUG, VSH_ERR_ERROR);
+ exit(EXIT_FAILURE);
+ }
- if (keepalive < 0) {
- vshError(ctl,
- _("option %s requires a positive integer argument"),
- longindex == -1 ? "-K" : "--keepalive-count");
- exit(EXIT_FAILURE);
- }
- ctl->keepalive_count = keepalive;
- break;
- case 'l':
- vshCloseLogFile(ctl);
- ctl->logfile = vshStrdup(ctl, optarg);
- vshOpenLogFile(ctl);
- break;
- case 'q':
- ctl->quiet = true;
- break;
- case 't':
- ctl->timing = true;
- break;
- case 'r':
- priv->readonly = true;
- break;
- case 'v':
- if (STRNEQ_NULLABLE(optarg, "long")) {
- puts(VERSION);
- exit(EXIT_SUCCESS);
- }
- ATTRIBUTE_FALLTHROUGH;
- case 'V':
- virshShowVersion(ctl);
- exit(EXIT_SUCCESS);
- case ':':
- for (i = 0; opt[i].name != NULL; i++) {
- if (opt[i].val == optopt)
- break;
- }
- if (opt[i].name)
- vshError(ctl, _("option '-%c'/'--%s' requires an argument"),
- optopt, opt[i].name);
- else
- vshError(ctl, _("option '-%c' requires an argument"), optopt);
+ if (keepalive_interval != INT_MAX) {
+ if (keepalive_interval < 0) {
+ vshError(ctl,
+ _("keepalive interval requires a positive integer"));
exit(EXIT_FAILURE);
- case '?':
- if (optopt)
- vshError(ctl, _("unsupported option '-%c'. See --help."), optopt);
- else
- vshError(ctl, _("unsupported option '%s'. See --help."), argv[optind - 1]);
- exit(EXIT_FAILURE);
- default:
- vshError(ctl, _("unknown option"));
+ }
+ ctl->keepalive_interval = keepalive_interval;
+ }
+
+ if (keepalive_count != INT_MAX) {
+ if (keepalive_count < 0) {
+ vshError(ctl,
+ _("keepalive count requires a positive integer"));
exit(EXIT_FAILURE);
}
- longindex = -1;
+ ctl->keepalive_count = keepalive_count;
+ }
+
+ len = strlen(priv->escapeChar);
+ if (!((len == 2 && *priv->escapeChar == '^' &&
+ virshAllowedEscapeChar(priv->escapeChar[1])) ||
+ (len == 1 && *priv->escapeChar != '^'))) {
+ vshError(ctl, _("Invalid string '%s' for escape sequence"),
+ priv->escapeChar);
+ exit(EXIT_FAILURE);
+ }
+
+ if (version) {
+ virshShowVersion(ctl);
+ exit(EXIT_SUCCESS);
+ }
+
+ if (logfile) {
+ vshCloseLogFile(ctl);
+ ctl->logfile = logfile;
+ vshOpenLogFile(ctl);
}
- if (argc == optind) {
+ if (argc == 1) {
ctl->imode = true;
} else {
/* parse command */
ctl->imode = false;
- if (argc - optind == 1) {
- vshDebug(ctl, VSH_ERR_INFO, "commands: \"%s\"\n", argv[optind]);
- return vshCommandStringParse(ctl, argv[optind], NULL);
+ if (argc == 2) {
+ vshDebug(ctl, VSH_ERR_INFO, "commands: \"%s\"\n", argv[1]);
+ return vshCommandStringParse(ctl, argv[1], NULL);
} else {
- return vshCommandArgvParse(ctl, argc - optind, argv + optind);
+ return vshCommandArgvParse(ctl, argc - 1, argv + 1);
}
}
return true;
--
2.21.0
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On Fri, Sep 27, 2019 at 06:17:31PM +0100, Daniel P. Berrangé wrote:
> The GOptionContext API has the benefit over getopt_long that it will
> automatically handle --help output formatting.
>
> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> ---
> tools/virsh.c | 303 ++++++++++++++++++++++----------------------------
> 1 file changed, 135 insertions(+), 168 deletions(-)
>
> diff --git a/tools/virsh.c b/tools/virsh.c
> index ec20f35a77..6c469ff576 100644
> --- a/tools/virsh.c
> +++ b/tools/virsh.c
> @@ -23,7 +23,6 @@
>
> #include <stdarg.h>
> #include <unistd.h>
> -#include <getopt.h>
> #include <sys/time.h>
> #include <fcntl.h>
> #include <time.h>
> @@ -445,53 +444,36 @@ virshDeinit(vshControl *ctl)
> }
>
> /*
> - * Print usage
> + * Build help description for commands
> */
> -static void
> -virshUsage(void)
> +static char *
> +virshBuildDescription(void)
> {
> const vshCmdGrp *grp;
> const vshCmdDef *cmd;
> -
> - fprintf(stdout, _("\n%s [options]... [<command_string>]"
> - "\n%s [options]... <command> [args...]\n\n"
> - " options:\n"
> - " -c | --connect=URI hypervisor connection URI\n"
> - " -d | --debug=NUM debug level [0-4]\n"
> - " -e | --escape <char> set escape sequence for console\n"
> - " -h | --help this help\n"
> - " -k | --keepalive-interval=NUM\n"
> - " keepalive interval in seconds, 0 for disable\n"
> - " -K | --keepalive-count=NUM\n"
> - " number of possible missed keepalive messages\n"
> - " -l | --log=FILE output logging to file\n"
> - " -q | --quiet quiet mode\n"
> - " -r | --readonly connect readonly\n"
> - " -t | --timing print timing information\n"
> - " -v short version\n"
> - " -V long version\n"
> - " --version[=TYPE] version, TYPE is short or long (default short)\n"
> - " commands (non interactive mode):\n\n"), progname,
> - progname);
> + GString *str = g_string_new("Commands (non interactive mode):\n\n");
>
> for (grp = cmdGroups; grp->name; grp++) {
> - fprintf(stdout, _(" %s (help keyword '%s')\n"),
> - grp->name, grp->keyword);
> + g_string_append_printf(str,
> + _(" %s (help keyword '%s')\n"),
> + grp->name, grp->keyword);
> for (cmd = grp->commands; cmd->name; cmd++) {
> if (cmd->flags & VSH_CMD_FLAG_ALIAS)
> continue;
> - fprintf(stdout,
> - " %-30s %s\n", cmd->name,
> - _(vshCmddefGetInfo(cmd, "help")));
> + g_string_append_printf(str,
> + " %-30s %s\n",
> + cmd->name,
> + _(vshCmddefGetInfo(cmd, "help")));
> }
> - fprintf(stdout, "\n");
> + g_string_append_printf(str, "\n");
> }
>
> - fprintf(stdout, "%s",
> - _("\n (specify help <group> for details about the commands in the group)\n"));
> - fprintf(stdout, "%s",
> - _("\n (specify help <command> for details about the command)\n\n"));
> - return;
> + g_string_append_printf(str,
> + _("Specify help <group> for details about the commands in the group)\n"));
> + g_string_append_printf(str,
> + _("Specify help <command> for details about the command)\n"));
> +
> + return g_string_free(str, FALSE);
> }
>
> /*
> @@ -647,6 +629,22 @@ virshAllowedEscapeChar(char c)
> ('@' <= c && c <= '_');
> }
>
> +static gboolean
> +virshVersion(const gchar *option_name G_GNUC_UNUSED,
> + const gchar *value,
> + gpointer data,
> + GError **error G_GNUC_UNUSED)
> +{
> + vshControl *ctl = data;
> +
> + if (value == NULL || STRNEQ(value, "long"))
> + puts(VERSION);
> + else
> + virshShowVersion(ctl);
> +
> + exit(EXIT_SUCCESS);
> +}
> +
> /*
> * argv[]: virsh [options] [command]
> *
> @@ -654,152 +652,121 @@ virshAllowedEscapeChar(char c)
> static bool
> virshParseArgv(vshControl *ctl, int argc, char **argv)
> {
> - int arg, len, debug, keepalive;
> - size_t i;
> - int longindex = -1;
> + int debug = 0;
> + bool version = false;
> + size_t len;
> virshControlPtr priv = ctl->privData;
> - struct option opt[] = {
> - {"connect", required_argument, NULL, 'c'},
> - {"debug", required_argument, NULL, 'd'},
> - {"escape", required_argument, NULL, 'e'},
> - {"help", no_argument, NULL, 'h'},
> - {"keepalive-interval", required_argument, NULL, 'k'},
> - {"keepalive-count", required_argument, NULL, 'K'},
> - {"log", required_argument, NULL, 'l'},
> - {"quiet", no_argument, NULL, 'q'},
> - {"readonly", no_argument, NULL, 'r'},
> - {"timing", no_argument, NULL, 't'},
> - {"version", optional_argument, NULL, 'v'},
> - {NULL, 0, NULL, 0}
> + char *logfile = NULL;
> + int keepalive_interval = INT_MAX;
> + int keepalive_count = INT_MAX;
> + GOptionEntry opt[] = {
> + { "connect", 'c', 0,
> + G_OPTION_ARG_STRING, &ctl->connname,
> + _("hypervisor connection URI"), "URI" },
> + { "debug", 'd', 0,
> + G_OPTION_ARG_INT, &debug,
> + _("debug level [0-4]\n"), "LEVEL" },
> + { "escape", 'e', 0,
> + G_OPTION_ARG_STRING, &priv->escapeChar,
> + _("set escape sequence for console"), "ESCAPE" },
> + { "keepalive-interval", 'k', 0,
> + G_OPTION_ARG_INT, &keepalive_interval,
> + _("keepalive interval in seconds, 0 for disable"), "SECS" },
> + { "keepalive-count", 'K', 0,
> + G_OPTION_ARG_INT, &keepalive_count,
> + _("number of possible missed keepalive messages"), "NUM" },
> + { "log", 'l', 0,
> + G_OPTION_ARG_STRING, &logfile,
> + _("output logging to file"), "FILENAME" },
> + { "quiet", 'q', 0,
> + G_OPTION_ARG_NONE, &ctl->quiet,
> + _("quite mode"), NULL },
> + { "readonly", 'r', 0,
> + G_OPTION_ARG_NONE, &priv->readonly,
> + _("connect readonly"), NULL },
> + { "timing", 't', 0,
> + G_OPTION_ARG_NONE, &ctl->timing,
> + _("print timing information"), NULL },
> + { "version", 'v', G_OPTION_FLAG_OPTIONAL_ARG,
> + G_OPTION_ARG_CALLBACK, virshVersion,
> + _("print short version"), "[short]" },
> + { "version", 'V', 0,
> + G_OPTION_ARG_NONE, &version,
> + _("print long version"), "long" },
We should be able to have both -v and -V call virshVersion if the
functions will look like this:
static gboolean
virshVersion(const gchar *option_name,
const gchar *value,
gpointer data,
GError **error G_GNUC_UNUSED)
{
vshControl *ctl = data;
if (STREQ(option_name, "-V") || STREQ_NULLABLE(value, "long"))
virshShowVersion(ctl);
else
puts(VERSION);
exit(EXIT_SUCCESS);
}
That way we will have only a single place where the version printing
code is.
Otherwise looks good to me.
Pavel
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On Tue, Oct 01, 2019 at 11:37:17AM +0200, Pavel Hrdina wrote:
> On Fri, Sep 27, 2019 at 06:17:31PM +0100, Daniel P. Berrangé wrote:
> > The GOptionContext API has the benefit over getopt_long that it will
> > automatically handle --help output formatting.
> >
> > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > ---
> > tools/virsh.c | 303 ++++++++++++++++++++++----------------------------
> > 1 file changed, 135 insertions(+), 168 deletions(-)
> >
> > diff --git a/tools/virsh.c b/tools/virsh.c
> > index ec20f35a77..6c469ff576 100644
> > --- a/tools/virsh.c
> > +++ b/tools/virsh.c
> > @@ -23,7 +23,6 @@
> >
> > #include <stdarg.h>
> > #include <unistd.h>
> > -#include <getopt.h>
> > #include <sys/time.h>
> > #include <fcntl.h>
> > #include <time.h>
> > @@ -445,53 +444,36 @@ virshDeinit(vshControl *ctl)
> > }
> > + { "version", 'v', G_OPTION_FLAG_OPTIONAL_ARG,
> > + G_OPTION_ARG_CALLBACK, virshVersion,
> > + _("print short version"), "[short]" },
> > + { "version", 'V', 0,
> > + G_OPTION_ARG_NONE, &version,
> > + _("print long version"), "long" },
>
> We should be able to have both -v and -V call virshVersion if the
> functions will look like this:
>
> static gboolean
> virshVersion(const gchar *option_name,
> const gchar *value,
> gpointer data,
> GError **error G_GNUC_UNUSED)
> {
> vshControl *ctl = data;
>
> if (STREQ(option_name, "-V") || STREQ_NULLABLE(value, "long"))
> virshShowVersion(ctl);
> else
> puts(VERSION);
>
> exit(EXIT_SUCCESS);
> }
>
> That way we will have only a single place where the version printing
> code is.
Hmm, so "option_name" in the callback is the option that the user
actually passed ? I was thinking it was the option name from the
static array - ie it would always be "version". If you're right
though, this is definitely my preference.
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On Tue, Oct 01, 2019 at 10:48:50AM +0100, Daniel P. Berrangé wrote:
> On Tue, Oct 01, 2019 at 11:37:17AM +0200, Pavel Hrdina wrote:
> > On Fri, Sep 27, 2019 at 06:17:31PM +0100, Daniel P. Berrangé wrote:
> > > The GOptionContext API has the benefit over getopt_long that it will
> > > automatically handle --help output formatting.
> > >
> > > Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
> > > ---
> > > tools/virsh.c | 303 ++++++++++++++++++++++----------------------------
> > > 1 file changed, 135 insertions(+), 168 deletions(-)
> > >
> > > diff --git a/tools/virsh.c b/tools/virsh.c
> > > index ec20f35a77..6c469ff576 100644
> > > --- a/tools/virsh.c
> > > +++ b/tools/virsh.c
> > > @@ -23,7 +23,6 @@
> > >
> > > #include <stdarg.h>
> > > #include <unistd.h>
> > > -#include <getopt.h>
> > > #include <sys/time.h>
> > > #include <fcntl.h>
> > > #include <time.h>
> > > @@ -445,53 +444,36 @@ virshDeinit(vshControl *ctl)
> > > }
>
> > > + { "version", 'v', G_OPTION_FLAG_OPTIONAL_ARG,
> > > + G_OPTION_ARG_CALLBACK, virshVersion,
> > > + _("print short version"), "[short]" },
> > > + { "version", 'V', 0,
> > > + G_OPTION_ARG_NONE, &version,
> > > + _("print long version"), "long" },
> >
> > We should be able to have both -v and -V call virshVersion if the
> > functions will look like this:
> >
> > static gboolean
> > virshVersion(const gchar *option_name,
> > const gchar *value,
> > gpointer data,
> > GError **error G_GNUC_UNUSED)
> > {
> > vshControl *ctl = data;
> >
> > if (STREQ(option_name, "-V") || STREQ_NULLABLE(value, "long"))
> > virshShowVersion(ctl);
> > else
> > puts(VERSION);
> >
> > exit(EXIT_SUCCESS);
> > }
> >
> > That way we will have only a single place where the version printing
> > code is.
>
> Hmm, so "option_name" in the callback is the option that the user
> actually passed ? I was thinking it was the option name from the
> static array - ie it would always be "version". If you're right
> though, this is definitely my preference.
It is the option actually used by the user, from the glib docs:
option_name The name of the option being parsed. This will be either
a single dash followed by a single letter (for a short
name) or two dashes followed by a long option name.
Pavel
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2026 Red Hat, Inc.