aboutsummaryrefslogtreecommitdiffstats
path: root/common/init.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2021-03-04 09:16:48 +0000
committerWerner Koch <[email protected]>2021-03-04 09:22:14 +0000
commitdeb6c94362c0f179de1cac18707aad2f51a21e10 (patch)
treedec21d341c77aaa92fdf0ecf8c36a789aad3746c /common/init.c
parentgpg: Keep temp files when opening images via xdg-open (diff)
downloadgnupg-deb6c94362c0f179de1cac18707aad2f51a21e10.tar.gz
gnupg-deb6c94362c0f179de1cac18707aad2f51a21e10.zip
common: First take on handling Unicode command line args.
* common/w32-misc.c: New. * common/t-w32-cmdline.c: New. * common/init.c: Include w32help.h. (prepare_w32_commandline): New. (_init_common_subsystems) [W32]: Call prepare_w32_commandline. * common/Makefile.am (common_sources) [W32]: Add w32-misc.c (module_tests): Add t-w32-cmdline (t_w32_cmdline_LDADD): New. -- The rules for the command line parser are not cleary specified - if at all. See the comment in t-w32-cmdline.c. We can't use the mingw version because that would require to change all argv handling to be wchar_t and that only for Windows. That would be too ugly. Parsing the command line into argv by us is much easier and we can do that only if needed - i.e. if globing is required (we are prepared for this) or a non-ASCII character has been encountered. This way we keep things stable and only fix the currently not working Unicode problem. GnuPG-bug-id: 4398
Diffstat (limited to 'common/init.c')
-rw-r--r--common/init.c78
1 files changed, 74 insertions, 4 deletions
diff --git a/common/init.c b/common/init.c
index 073c5cd8a..06fd30956 100644
--- a/common/init.c
+++ b/common/init.c
@@ -42,6 +42,7 @@
#include <gcrypt.h>
#include "util.h"
#include "i18n.h"
+#include "w32help.h"
/* This object is used to register memory cleanup functions.
Technically they are not needed but they can avoid frequent
@@ -79,6 +80,11 @@ sleep_on_exit (void)
}
#endif /*HAVE_W32CE_SYSTEM*/
+#if HAVE_W32_SYSTEM
+static void prepare_w32_commandline (int *argcp, char ***argvp);
+#endif /*HAVE_W32_SYSTEM*/
+
+
static void
run_mem_cleanup (void)
@@ -190,13 +196,10 @@ _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp)
gpgrt_init ();
gpgrt_set_alloc_func (gcry_realloc);
+#ifdef HAVE_W32CE_SYSTEM
/* Special hack for Windows CE: We extract some options from arg
to setup the standard handles. */
-#ifdef HAVE_W32CE_SYSTEM
parse_std_file_handles (argcp, argvp);
-#else
- (void)argcp;
- (void)argvp;
#endif
/* Access the standard estreams as early as possible. If we don't
@@ -217,6 +220,16 @@ _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp)
/* Logging shall use the standard socket directory as fallback. */
log_set_socket_dir_cb (gnupg_socketdir);
+
+#if HAVE_W32_SYSTEM
+ /* For Standard Windows we use our own parser for the command line
+ * so that we can return an array of utf-8 encoded strings. */
+ prepare_w32_commandline (argcp, argvp);
+#else
+ (void)argcp;
+ (void)argvp;
+#endif
+
}
@@ -290,3 +303,60 @@ parse_std_file_handles (int *argcp, char ***argvp)
}
#endif /*HAVE_W32CE_SYSTEM*/
+
+
+/* For Windows we need to parse the command line so that we can
+ * provide an UTF-8 encoded argv. If there is any Unicode character
+ * we return a new array but if there is no Unicode character we do
+ * nothing. */
+#ifdef HAVE_W32_SYSTEM
+static void
+prepare_w32_commandline (int *r_argc, char ***r_argv)
+{
+ const wchar_t *wcmdline, *ws;
+ char *cmdline;
+ int argc;
+ char **argv;
+ const char *s;
+ int globing;
+
+ s = gpgrt_strusage (95);
+ globing = (s && *s == '1');
+
+ wcmdline = GetCommandLineW ();
+ if (!wcmdline)
+ {
+ log_error ("GetCommandLineW failed\n");
+ return; /* Ooops. */
+ }
+
+ if (!globing)
+ {
+ /* If globbing is not enabled we use our own parser only if
+ * there are any non-ASCII characters. */
+ for (ws=wcmdline; *ws; ws++)
+ if (!iswascii (*ws))
+ break;
+ if (!*ws)
+ return; /* No Unicode - return directly. */
+ }
+
+ cmdline = wchar_to_utf8 (wcmdline);
+ if (!cmdline)
+ {
+ log_error ("parsing command line failed: %s\n", strerror (errno));
+ return; /* Ooops. */
+ }
+ gpgrt_annotate_leaked_object (cmdline);
+
+ argv = w32_parse_commandline (cmdline, globing, &argc);
+ if (!argv)
+ {
+ log_error ("parsing command line failed: %s\n", "internal error");
+ return; /* Ooops. */
+ }
+ gpgrt_annotate_leaked_object (argv);
+ *r_argv = argv;
+ *r_argc = argc;
+}
+#endif /*HAVE_W32_SYSTEM*/