On Thu, Feb 22, 2024 at 12:15:45AM +0300, Michael Tokarev wrote: > In order to correctly print executable name in various > error messages, pass argv[0] to error_exit() function. > This way, error messages will refer to actual executable > name, which may be different from 'qemu-img'. > > For subcommands, pass whole argv[] array, so argv[0] is > the executable name, not subcommand name. In order to > do that, avoid resetting optind but continue with the > next option. Also don't require at least 3 options on > the command line: it makes no sense with options before > subcommand. > > Before invoking a subcommand, replace argv[0] to include > the subcommand name. > > Introduce tryhelp() function which just prints > > try 'command-name --help' for more info > > and exits. When tryhelp() is called from within a subcommand > handler, the message will look like: > > try 'command-name subcommand --help' for more info > > qemu-img uses getopt_long() with ':' as the first char in > optstring parameter, which means it doesn't print error > messages but return ':' or '?' instead, and qemu-img uses > unrecognized_option() or missing_argument() function to > print error messages. But it doesn't quite work: > > $ ./qemu-img -xx > qemu-img: unrecognized option './qemu-img' > > so the aim is to let getopt_long() to print regular error > messages instead (removing ':' prefix from optstring) and > remove handling of '?' and ':' "options" entirely. With > concatenated argv[0] and the subcommand, it all finally > does the right thing in all cases. This will be done in > subsequent changes command by command, with main() done > last. > > unrecognized_option() and missing_argument() functions > prototypes aren't changed by this patch, since they're > called from many places and will be removed a few patches > later. Only artifical "qemu-img" argv0 is provided in > there for now. > > Signed-off-by: Michael Tokarev <m...@tls.msk.ru> > --- > qemu-img.c | 75 +++++++++++++++++++++++++++--------------------------- > 1 file changed, 38 insertions(+), 37 deletions(-) > @@ -5602,10 +5602,11 @@ int main(int argc, char **argv) > /* find the command */ > for (cmd = img_cmds; cmd->name != NULL; cmd++) { > if (!strcmp(cmdname, cmd->name)) { > + argv[0] = g_strdup_printf("%s %s", argv[0], cmdname); > return cmd->handler(argc, argv);
This is going to result in valgrind warning that argv[0] is leaked. How about: g_autofree char *cmdargv0 = g_strdup_printf("%s %s", argv[0], cmdname); argv[0] = cmdargv0; return cmd->handler(argc, argv); > } > } > > /* not found */ > - error_exit("Command not found: %s", cmdname); > + error_exit(argv[0], "Command not found: %s", cmdname); > } > -- > 2.39.2 > > With 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 :|