[evolution-data-server] IMAPX: Use GSubprocess to implement the shell-command setting.
- From: Matthew Barnes <mbarnes src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server] IMAPX: Use GSubprocess to implement the shell-command setting.
- Date: Sun, 23 Feb 2014 16:09:40 +0000 (UTC)
commit ae9251900ac896490225043ad397de78974f2021
Author: Matthew Barnes <mbarnes redhat com>
Date: Wed Jan 22 14:00:28 2014 -0500
IMAPX: Use GSubprocess to implement the shell-command setting.
GSubprocess returns separate input/output streams for stdout/stdin,
and therefore can't be wrapped in a CamelStream. So this (hidden)
feature is broken until I can fully port IMAPX to GIO streams.
Also, GSubprocess is only available in GLib 2.39, so attempts to
use this feature with an older GLib will fail with a helpful error
message.
camel/providers/imapx/camel-imapx-server.c | 225 +++++++++++++---------------
camel/providers/imapx/camel-imapx-server.h | 1 -
2 files changed, 103 insertions(+), 123 deletions(-)
---
diff --git a/camel/providers/imapx/camel-imapx-server.c b/camel/providers/imapx/camel-imapx-server.c
index 14c80f6..7369c92 100644
--- a/camel/providers/imapx/camel-imapx-server.c
+++ b/camel/providers/imapx/camel-imapx-server.c
@@ -19,6 +19,13 @@
#include <config.h>
#endif
+/* XXX Disable deprecation warnings until we require GLib 2.40.
+ *
+ * This silences warnings for using GSubprocess functions, which are
+ * only available as of GLib 2.39. But we do so conditionally, with
+ * GLIB_CHECK_VERSION macros. */
+#define GLIB_DISABLE_DEPRECATION_WARNINGS
+
#include <time.h>
#include <errno.h>
#include <glib/gstdio.h>
@@ -326,7 +333,11 @@ struct _CamelIMAPXServerPrivate {
CamelIMAPXServerUntaggedContext *context;
GHashTable *untagged_handlers;
+ /* The 'stream_lock' also guards the GSubprocess. */
CamelIMAPXStream *stream;
+#if GLIB_CHECK_VERSION(2,39,0)
+ GSubprocess *subprocess;
+#endif
GMutex stream_lock;
GThread *parser_thread;
@@ -4178,27 +4189,23 @@ imapx_maybe_select (CamelIMAPXServer *is,
camel_imapx_command_unref (ic);
}
-#ifndef G_OS_WIN32
-
-/* Using custom commands to connect to IMAP servers is not supported on Win32 */
-
-static CamelStream *
+static gboolean
connect_to_server_process (CamelIMAPXServer *is,
const gchar *cmd,
GError **error)
{
+#if GLIB_CHECK_VERSION(2,39,0)
+ GSubprocessLauncher *launcher;
+ GSubprocess *subprocess = NULL;
CamelNetworkSettings *network_settings;
CamelProvider *provider;
CamelSettings *settings;
- CamelStream *cmd_stream;
- CamelStream *imapx_stream;
CamelIMAPXStore *store;
CamelURL url;
- gint ret, i = 0;
+ gchar **argv = NULL;
gchar *buf;
gchar *cmd_copy;
gchar *full_cmd;
- gchar *child_env[7];
const gchar *password;
gchar *host;
gchar *user;
@@ -4206,6 +4213,11 @@ connect_to_server_process (CamelIMAPXServer *is,
memset (&url, 0, sizeof (CamelURL));
+ launcher = g_subprocess_launcher_new (
+ G_SUBPROCESS_FLAGS_STDIN_PIPE |
+ G_SUBPROCESS_FLAGS_STDOUT_PIPE |
+ G_SUBPROCESS_FLAGS_STDERR_SILENCE);
+
store = camel_imapx_server_ref_store (is);
password = camel_service_get_password (CAMEL_SERVICE (store));
@@ -4224,17 +4236,30 @@ connect_to_server_process (CamelIMAPXServer *is,
camel_url_set_port (&url, port);
camel_url_set_user (&url, user);
buf = camel_url_to_string (&url, 0);
- child_env[i++] = g_strdup_printf ("URL=%s", buf);
- g_free (buf);
- child_env[i++] = g_strdup_printf ("URLHOST=%s", host);
- if (port)
- child_env[i++] = g_strdup_printf ("URLPORT=%u", port);
- if (user)
- child_env[i++] = g_strdup_printf ("URLUSER=%s", user);
- if (password)
- child_env[i++] = g_strdup_printf ("URLPASSWD=%s", password);
- child_env[i] = NULL;
+ g_subprocess_launcher_setenv (launcher, "URL", buf, TRUE);
+ g_subprocess_launcher_setenv (launcher, "URLHOST", host, TRUE);
+
+ if (port > 0) {
+ gchar *port_string;
+
+ port_string = g_strdup_printf ("%u", port);
+ g_subprocess_launcher_setenv (
+ launcher, "URLPORT", port_string, TRUE);
+ g_free (port_string);
+ }
+
+ if (user != NULL) {
+ g_subprocess_launcher_setenv (
+ launcher, "URLPORT", user, TRUE);
+ }
+
+ if (password != NULL) {
+ g_subprocess_launcher_setenv (
+ launcher, "URLPASSWD", password, TRUE);
+ }
+
+ g_free (buf);
g_object_unref (settings);
g_object_unref (store);
@@ -4288,41 +4313,41 @@ connect_to_server_process (CamelIMAPXServer *is,
g_free (host);
g_free (user);
- /* FIXME Use GSubprocess here as soon as we can. */
+ if (g_shell_parse_argv (full_cmd, NULL, &argv, error)) {
+ subprocess = g_subprocess_launcher_spawnv (
+ launcher, (const gchar * const *) argv, error);
+ g_strfreev (argv);
+ }
- cmd_stream = camel_stream_process_new ();
+ g_free (full_cmd);
+ g_object_unref (launcher);
- ret = camel_stream_process_connect (
- CAMEL_STREAM_PROCESS (cmd_stream),
- full_cmd, (const gchar **) child_env, error);
+ if (subprocess != NULL) {
+ g_mutex_lock (&is->priv->stream_lock);
- while (i)
- g_free (child_env[--i]);
+ g_warn_if_fail (is->priv->subprocess == NULL);
- if (ret == -1) {
- g_object_unref (cmd_stream);
- g_free (full_cmd);
- return NULL;
- }
+ is->priv->subprocess = g_object_ref (subprocess);
- g_free (full_cmd);
+ g_mutex_unlock (&is->priv->stream_lock);
- imapx_stream = camel_imapx_stream_new (cmd_stream);
+ g_object_unref (subprocess);
+ }
- g_object_unref (cmd_stream);
+ /* FIXME Temporarily broken. Need to port the rest of
+ * IMAPX to use GInput/OutputStream directly. */
+ return FALSE;
- /* Server takes ownership of the IMAPX stream. */
- g_mutex_lock (&is->priv->stream_lock);
- g_warn_if_fail (is->priv->stream == NULL);
- is->priv->stream = CAMEL_IMAPX_STREAM (imapx_stream);
- is->is_process_stream = TRUE;
- g_mutex_unlock (&is->priv->stream_lock);
+#else /* GLIB_CHECK_VERSION(2,39,0) */
- g_object_notify (G_OBJECT (is), "stream");
+ g_set_error_literal (
+ error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+ "GLib 2.39 or later is required to connect "
+ "to an IMAP server through a shell command");
- return imapx_stream;
+ return FALSE;
+#endif
}
-#endif /* G_OS_WIN32 */
gboolean
imapx_connect_to_server (CamelIMAPXServer *is,
@@ -4342,15 +4367,12 @@ imapx_connect_to_server (CamelIMAPXServer *is,
guchar *token;
gint tok;
CamelIMAPXCommand *ic;
+ gchar *shell_command = NULL;
+ gboolean use_shell_command;
gboolean success = TRUE;
gchar *host;
GError *local_error = NULL;
-#ifndef G_OS_WIN32
- gboolean use_shell_command;
- gchar *shell_command = NULL;
-#endif
-
store = camel_imapx_server_ref_store (is);
settings = camel_service_ref_settings (CAMEL_SERVICE (store));
@@ -4359,30 +4381,25 @@ imapx_connect_to_server (CamelIMAPXServer *is,
host = camel_network_settings_dup_host (network_settings);
method = camel_network_settings_get_security_method (network_settings);
-#ifndef G_OS_WIN32
use_shell_command = camel_imapx_settings_get_use_shell_command (
CAMEL_IMAPX_SETTINGS (settings));
if (use_shell_command)
shell_command = camel_imapx_settings_dup_shell_command (
CAMEL_IMAPX_SETTINGS (settings));
-#endif
g_object_unref (settings);
-#ifndef G_OS_WIN32
if (shell_command != NULL) {
- imapx_stream = connect_to_server_process (
- is, shell_command, &local_error);
+ success = connect_to_server_process (is, shell_command, error);
g_free (shell_command);
- if (imapx_stream != NULL)
+ if (success)
goto connected;
else
goto exit;
}
-#endif
base_stream = camel_network_service_connect_sync (
CAMEL_NETWORK_SERVICE (store), cancellable, error);
@@ -7425,7 +7442,8 @@ imapx_abort_all_commands (CamelIMAPXServer *is,
/* ********************************************************************** */
static gboolean
-imapx_parse_contents (CamelIMAPXServer *is)
+imapx_ready_to_read (GInputStream *input_stream,
+ CamelIMAPXServer *is)
{
CamelIMAPXStream *stream;
GCancellable *cancellable;
@@ -7478,21 +7496,6 @@ imapx_parse_contents (CamelIMAPXServer *is)
return G_SOURCE_CONTINUE;
}
-static gboolean
-imapx_ready_to_read (GInputStream *input_stream,
- CamelIMAPXServer *is)
-{
- return imapx_parse_contents (is);
-}
-
-static gboolean
-imapx_process_ready_to_read (gint fd,
- GIOCondition condition,
- CamelIMAPXServer *is)
-{
- return imapx_parse_contents (is);
-}
-
/*
* The main processing (reading) loop.
*
@@ -7506,8 +7509,10 @@ imapx_parser_thread (gpointer user_data)
CamelIMAPXServer *is;
CamelIMAPXStore *store;
CamelIMAPXStream *stream;
- CamelStream *source_stream;
+ GIOStream *base_stream = NULL;
+ GInputStream *input_stream = NULL;
GCancellable *cancellable;
+ GSource *pollable_source;
is = CAMEL_IMAPX_SERVER (user_data);
@@ -7522,65 +7527,38 @@ imapx_parser_thread (gpointer user_data)
stream = camel_imapx_server_ref_stream (is);
g_return_val_if_fail (stream != NULL, NULL);
- source_stream = camel_imapx_stream_ref_source (stream);
-
g_main_context_push_thread_default (is->priv->parser_main_context);
-#ifndef G_OS_WIN32
- if (is->is_process_stream) {
- GSource *unix_fd_source;
- GSource *cancellable_source;
- gint fd;
-
- /* FIXME Use GSubprocess here as soon as we can. */
-
- fd = CAMEL_STREAM_PROCESS (source_stream)->sockfd;
-
- cancellable_source = g_cancellable_source_new (cancellable);
- g_source_set_dummy_callback (cancellable_source);
-
- unix_fd_source = g_unix_fd_source_new (fd, G_IO_IN);
- g_source_add_child_source (
- unix_fd_source, cancellable_source);
- g_source_set_callback (
- unix_fd_source,
- (GSourceFunc) imapx_process_ready_to_read,
- g_object_ref (is),
- (GDestroyNotify) g_object_unref);
- g_source_attach (
- unix_fd_source,
- is->priv->parser_main_context);
- g_source_unref (unix_fd_source);
-
- g_source_unref (cancellable_source);
+#if GLIB_CHECK_VERSION(2,39,0)
+ if (is->priv->subprocess != NULL) {
+ input_stream =
+ g_subprocess_get_stdout_pipe (is->priv->subprocess);
+ }
+#endif
- } else
-#endif /* G_OS_WIN32 */
- {
- GIOStream *base_stream;
- GInputStream *input_stream;
- GSource *pollable_source;
+ if (input_stream == NULL) {
+ CamelStream *source_stream;
+ source_stream = camel_imapx_stream_ref_source (stream);
base_stream = camel_stream_ref_base_stream (source_stream);
input_stream = g_io_stream_get_input_stream (base_stream);
-
- pollable_source = g_pollable_input_stream_create_source (
- G_POLLABLE_INPUT_STREAM (input_stream), cancellable);
- g_source_set_callback (
- pollable_source,
- (GSourceFunc) imapx_ready_to_read,
- g_object_ref (is),
- (GDestroyNotify) g_object_unref);
- g_source_attach (
- pollable_source,
- is->priv->parser_main_context);
- g_source_unref (pollable_source);
-
- g_object_unref (base_stream);
+ g_object_unref (source_stream);
}
+ pollable_source = g_pollable_input_stream_create_source (
+ G_POLLABLE_INPUT_STREAM (input_stream), cancellable);
+ g_source_set_callback (
+ pollable_source,
+ (GSourceFunc) imapx_ready_to_read,
+ g_object_ref (is),
+ (GDestroyNotify) g_object_unref);
+ g_source_attach (
+ pollable_source,
+ is->priv->parser_main_context);
+ g_source_unref (pollable_source);
+
g_clear_object (&cancellable);
- g_clear_object (&source_stream);
+ g_clear_object (&base_stream);
g_clear_object (&stream);
g_main_loop_run (is->priv->parser_main_loop);
@@ -7690,6 +7668,9 @@ imapx_server_dispose (GObject *object)
g_weak_ref_set (&server->priv->store, NULL);
+#if GLIB_CHECK_VERSION(2,39,0)
+ g_clear_object (&server->priv->subprocess);
+#endif
g_clear_object (&server->priv->namespaces);
g_hash_table_remove_all (server->priv->mailboxes);
diff --git a/camel/providers/imapx/camel-imapx-server.h b/camel/providers/imapx/camel-imapx-server.h
index 9fd66de..c53e9bb 100644
--- a/camel/providers/imapx/camel-imapx-server.h
+++ b/camel/providers/imapx/camel-imapx-server.h
@@ -99,7 +99,6 @@ struct _CamelIMAPXServer {
/* Info about the current connection */
struct _capability_info *cinfo;
- gboolean is_process_stream;
/* incoming jobs */
GQueue jobs;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]