From 69cf8b1795e3304c93f1c7518596dd3b6522d11e Mon Sep 17 00:00:00 2001 From: Tony <45124675+sonninnos@users.noreply.github.com> Date: Mon, 28 Feb 2022 11:32:50 +0200 Subject: [PATCH] Fix some command line segfaults (#13682) --- libretro-common/compat/compat_getopt.c | 21 ++++++++++++++++++++- retroarch.c | 12 ++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/libretro-common/compat/compat_getopt.c b/libretro-common/compat/compat_getopt.c index 742cb920c9..cec68d499b 100644 --- a/libretro-common/compat/compat_getopt.c +++ b/libretro-common/compat/compat_getopt.c @@ -126,19 +126,38 @@ static int parse_short(const char *optstring, char * const *argv) static int parse_long(const struct option *longopts, char * const *argv) { size_t indice; + char *save = NULL; + char *argv0 = strdup(&argv[0][2]); + char *token = strtok_r(argv0, "=", &save); const struct option *opt = NULL; + for (indice = 0; longopts[indice].name; indice++) { - if (!strcmp(longopts[indice].name, &argv[0][2])) + if (token && !strcmp(longopts[indice].name, token)) { opt = &longopts[indice]; break; } } + free(argv0); + argv0 = NULL; + if (!opt) return '?'; + /* Handle args with '=' instead of space */ + if (opt->has_arg) + { + char *special_arg = strchr(argv[0], '='); + if (special_arg) + { + optarg = ++special_arg; + optind++; + return opt->val; + } + } + /* getopt_long has an "optional" arg, but we don't bother with that. */ if (opt->has_arg && !argv[1]) return '?'; diff --git a/retroarch.c b/retroarch.c index 665f0933ef..978fdd2d33 100644 --- a/retroarch.c +++ b/retroarch.c @@ -4064,7 +4064,7 @@ static void retroarch_print_version(void) frontend_driver_attach_console(); str[0] = '\0'; - fprintf(stderr, "%s: %s -- v%s", + fprintf(stdout, "%s: %s -- v%s", msg_hash_to_str(MSG_PROGRAM), msg_hash_to_str(MSG_LIBRETRO_FRONTEND), PACKAGE_VERSION); @@ -4095,7 +4095,7 @@ static void retroarch_print_help(const char *arg0) puts("==================================================================="); fputs("\n", stdout); - printf("Usage: %s [OPTIONS]... [FILE]\n\n", arg0); + fprintf(stdout, "Usage: %s [OPTIONS]... [FILE]\n\n", arg0); strlcat(buf, " -h, --help " "Show this help message.\n", sizeof(buf)); @@ -4655,8 +4655,12 @@ static bool retroarch_parse_input_and_config( /* Must handle '?' otherwise you get an infinite loop */ case '?': - retroarch_print_help(argv[0]); - retroarch_fail(1, "retroarch_parse_input()"); + frontend_driver_attach_console(); +#ifdef _WIN32 + fprintf(stderr, "\n%s: unrecognized option '%s'\n", argv[0], argv[optind]); +#endif + fprintf(stderr, "Try '%s --help' for more information\n", argv[0]); + exit(EXIT_FAILURE); break; /* All other arguments are handled in the second pass */ }