[Commits] [SCM] claws branch, master, updated. 3.17.8-31-gca2900689

paul at claws-mail.org paul at claws-mail.org
Tue Mar 9 09:12:40 CET 2021


The branch, master has been updated
       via  ca2900689a41acb63cdaab061effbca074acdf83 (commit)
      from  cf0a3f25900d81b64d98c643d833363451072de4 (commit)

Summary of changes:
 src/compose.c | 331 +++++++++++++++++++++++-----------------------------------
 src/compose.h |   3 +-
 2 files changed, 130 insertions(+), 204 deletions(-)


- Log -----------------------------------------------------------------
commit ca2900689a41acb63cdaab061effbca074acdf83
Author: Paul <paul at claws-mail.org>
Date:   Tue Mar 9 08:12:33 2021 +0000

    enable external editor on windows. patch by Thorsten Maerz

diff --git a/src/compose.c b/src/compose.c
index 7abba6b41..8a6e634ee 100644
--- a/src/compose.c
+++ b/src/compose.c
@@ -50,6 +50,9 @@
 #ifndef G_OS_WIN32  /* fixme we should have a configure test. */
 #include <libgen.h>
 #endif
+#ifdef G_OS_WIN32
+#include <windows.h>
+#endif
 
 #if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
 #  include <wchar.h>
@@ -363,12 +366,9 @@ static gboolean attach_property_key_pressed	(GtkWidget	*widget,
 						 gboolean	*cancelled);
 
 static void compose_exec_ext_editor		(Compose	*compose);
-#ifdef G_OS_UNIX
-static gint compose_exec_ext_editor_real	(const gchar	*file,
-						 GdkNativeWindow socket_wid);
 static gboolean compose_ext_editor_kill		(Compose	*compose);
-static gboolean compose_input_cb		(GIOChannel	*source,
-						 GIOCondition	 condition,
+static void compose_ext_editor_closed_cb	(GPid		 pid,
+						 gint		 exit_status,
 						 gpointer	 data);
 static void compose_set_ext_editor_sensitive	(Compose	*compose,
 						 gboolean	 sensitive);
@@ -377,7 +377,6 @@ static gboolean compose_get_ext_editor_uses_socket();
 static gboolean compose_ext_editor_plug_removed_cb
 						(GtkSocket      *socket,
 						 Compose        *compose);
-#endif /* G_OS_UNIX */
 
 static void compose_undo_state_changed		(UndoMain	*undostruct,
 						 gint		 undo_state,
@@ -9612,18 +9611,40 @@ static gboolean attach_property_key_pressed(GtkWidget *widget,
 	return FALSE;
 }
 
+static gboolean compose_can_autosave(Compose *compose)
+{
+	if (compose->privacy_system && compose->use_encryption)
+		return prefs_common.autosave && prefs_common.autosave_encrypted;
+	else
+		return prefs_common.autosave;
+}
+
+/**
+ * compose_exec_ext_editor:
+ *
+ * Open (and optionally embed) external editor
+ **/
 static void compose_exec_ext_editor(Compose *compose)
 {
-#ifdef G_OS_UNIX
 	gchar *tmp;
 	GtkWidget *socket;
 	GdkNativeWindow socket_wid = 0;
-	pid_t pid;
-	gint pipe_fds[2];
+	GPid pid;
+	GError *error = NULL;
+	gchar *cmd;
+	gchar *p, *s;
+	gchar **argv;
 
 	tmp = g_strdup_printf("%s%ctmpmsg.%p", get_tmp_dir(),
 			      G_DIR_SEPARATOR, compose);
 
+	if (compose_write_body_to_file(compose, tmp) < 0) {
+		alertpanel_error(_("Could not write the body to file:\n%s"),
+		                 tmp);
+		g_free(tmp);
+		return;
+	}
+
 	if (compose_get_ext_editor_uses_socket()) {
 		/* Only allow one socket */
 		if (compose->exteditor_socket != NULL) {
@@ -9647,78 +9668,110 @@ static void compose_exec_ext_editor(Compose *compose)
 		compose->exteditor_socket = socket;
 	}
 
-	if (pipe(pipe_fds) < 0) {
-		perror("pipe");
-		g_free(tmp);
-		return;
+	if (compose_get_ext_editor_cmd_valid()) {
+		if (compose_get_ext_editor_uses_socket()) {
+			p = g_strdup(prefs_common_get_ext_editor_cmd());
+			s = strstr(p, "%w");
+			s[1] = 'u';
+			if (strstr(p, "%s") < s)
+				cmd = g_strdup_printf(p, tmp, socket_wid);
+			else
+				cmd = g_strdup_printf(p, socket_wid, tmp);
+			g_free(p);
+		} else {
+			cmd = g_strdup_printf(prefs_common_get_ext_editor_cmd(), tmp);
+		}
+	} else {
+		if (prefs_common_get_ext_editor_cmd())
+			g_warning("External editor command-line is invalid: '%s'",
+				  prefs_common_get_ext_editor_cmd());
+		cmd = g_strdup_printf(DEFAULT_EDITOR_CMD, tmp);
 	}
 
-	if ((pid = fork()) < 0) {
-		perror("fork");
+	argv = strsplit_with_quote(cmd, " ", 0);
+
+	if (!g_spawn_async(NULL, argv, NULL,
+			   G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+			   NULL, NULL, &pid, &error)) {
+		alertpanel_error(_("Could not spawn the following "
+				 "command:\n%s\n%s"),
+				 cmd, error ? error->message : _("Unknown error"));
+		if (error)
+			g_error_free(error);
 		g_free(tmp);
+		g_free(cmd);
+		g_strfreev(argv);
 		return;
 	}
+	g_free(cmd);
+	g_strfreev(argv);
 
-	if (pid != 0) {
-		/* close the write side of the pipe */
-		close(pipe_fds[1]);
+	compose->exteditor_file    = g_strdup(tmp);
+	compose->exteditor_pid     = pid;
+	compose->exteditor_tag     = g_child_watch_add(pid,
+						       compose_ext_editor_closed_cb,
+						       compose);
 
-		compose->exteditor_file    = g_strdup(tmp);
-		compose->exteditor_pid     = pid;
+	compose_set_ext_editor_sensitive(compose, FALSE);
 
-		compose_set_ext_editor_sensitive(compose, FALSE);
+	g_free(tmp);
+}
 
-#ifndef G_OS_WIN32
-		compose->exteditor_ch = g_io_channel_unix_new(pipe_fds[0]);
-#else
-		compose->exteditor_ch = g_io_channel_win32_new_fd(pipe_fds[0]);
-#endif
-		compose->exteditor_tag = g_io_add_watch(compose->exteditor_ch,
-							G_IO_IN,
-							compose_input_cb,
-							compose);
-	} else {	/* process-monitoring process */
-		pid_t pid_ed;
+/**
+  * compose_ext_editor_cb:
+  *
+  * External editor has closed (called by g_child_watch)
+  **/
+static void compose_ext_editor_closed_cb(GPid pid, gint exit_status, gpointer data)
+{
+	Compose *compose = (Compose *)data;
+	GError *error = NULL;
+	GtkTextView *text = GTK_TEXT_VIEW(compose->text);
+	GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
+	GtkTextIter start, end;
+	gchar *chars;
 
-		if (setpgid(0, 0))
-			perror("setpgid");
+	if (!g_spawn_check_exit_status(exit_status, &error)) {
+		alertpanel_error(_("External editor stopped with an "
+				 "error:%s"),
+				 error ? error->message : _("Unknown error"));
+		if (error)
+			g_error_free(error);
+	}
+	g_spawn_close_pid(compose->exteditor_pid);
 
-		/* close the read side of the pipe */
-		close(pipe_fds[0]);
+	gtk_text_buffer_set_text(buffer, "", -1);
+	compose_insert_file(compose, compose->exteditor_file);
+	compose_changed_cb(NULL, compose);
 
-		if (compose_write_body_to_file(compose, tmp) < 0) {
-			fd_write_all(pipe_fds[1], "2\n", 2);
-			_exit(1);
-		}
+	/* Check if we should save the draft or not */
+	if (compose_can_autosave(compose))
+	  compose_draft((gpointer)compose, COMPOSE_AUTO_SAVE);
 
-		pid_ed = compose_exec_ext_editor_real(tmp, socket_wid);
-		if (pid_ed < 0) {
-			fd_write_all(pipe_fds[1], "1\n", 2);
-			_exit(1);
-		}
+	if (claws_unlink(compose->exteditor_file) < 0)
+		FILE_OP_ERROR(compose->exteditor_file, "unlink");
 
-		/* wait until editor is terminated */
-		waitpid(pid_ed, NULL, 0);
+	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(compose->text));
+	gtk_text_buffer_get_start_iter(buffer, &start);
+	gtk_text_buffer_get_end_iter(buffer, &end);
+	chars = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
+	if (chars && strlen(chars) > 0)
+		compose->modified = TRUE;
+	g_free(chars);
 
-		fd_write_all(pipe_fds[1], "0\n", 2);
+	compose_set_ext_editor_sensitive(compose, TRUE);
 
-		close(pipe_fds[1]);
-		_exit(0);
+	g_free(compose->exteditor_file);
+	compose->exteditor_file    = NULL;
+	compose->exteditor_pid     = -1;
+	compose->exteditor_tag     = -1;
+	if (compose->exteditor_socket) {
+		gtk_widget_destroy(compose->exteditor_socket);
+		compose->exteditor_socket = NULL;
 	}
 
-	g_free(tmp);
-#endif /* G_OS_UNIX */
 }
 
-static gboolean compose_can_autosave(Compose *compose)
-{
-	if (compose->privacy_system && compose->use_encryption)
-		return prefs_common.autosave && prefs_common.autosave_encrypted;
-	else
-		return prefs_common.autosave;
-}
-
-#ifdef G_OS_UNIX
 static gboolean compose_get_ext_editor_cmd_valid()
 {
 	gboolean has_s = FALSE;
@@ -9743,96 +9796,44 @@ static gboolean compose_get_ext_editor_cmd_valid()
 	return TRUE;
 }
 
-static gint compose_exec_ext_editor_real(const gchar *file, GdkNativeWindow socket_wid)
-{
-	gchar *buf;
-	gchar *p, *s;
-	gchar **cmdline;
-	pid_t pid;
-
-	cm_return_val_if_fail(file != NULL, -1);
-
-	if ((pid = fork()) < 0) {
-		perror("fork");
-		return -1;
-	}
-
-	if (pid != 0) return pid;
-
-	/* grandchild process */
-
-	if (setpgid(0, getppid()))
-		perror("setpgid");
-
-	if (compose_get_ext_editor_cmd_valid()) {
-		if (compose_get_ext_editor_uses_socket()) {
-			p = g_strdup(prefs_common_get_ext_editor_cmd());
-			s = strstr(p, "%w");
-			s[1] = 'u';
-			if (strstr(p, "%s") < s)
-				buf = g_strdup_printf(p, file, socket_wid);
-			else
-				buf = g_strdup_printf(p, socket_wid, file);
-			g_free(p);
-		} else {
-			buf = g_strdup_printf(prefs_common_get_ext_editor_cmd(), file);
-		}
-	} else {
-		if (prefs_common_get_ext_editor_cmd())
-			g_warning("External editor command-line is invalid: '%s'",
-				  prefs_common_get_ext_editor_cmd());
-		buf = g_strdup_printf(DEFAULT_EDITOR_CMD, file);
-	}
-
-	cmdline = strsplit_with_quote(buf, " ", 0);
-	g_free(buf);
-	execvp(cmdline[0], cmdline);
-
-	perror("execvp");
-	g_strfreev(cmdline);
-
-	_exit(1);
-}
-
 static gboolean compose_ext_editor_kill(Compose *compose)
 {
-	pid_t pgid = compose->exteditor_pid * -1;
+	GPid pid = compose->exteditor_pid;
 	gint ret;
 
-	ret = kill(pgid, 0);
-
-	if (ret == 0 || (ret == -1 && EPERM == errno)) {
+	if (pid > 0) {
 		AlertValue val;
 		gchar *msg;
 
 		msg = g_strdup_printf
 			(_("The external editor is still working.\n"
 			   "Force terminating the process?\n"
-			   "process group id: %d"), -pgid);
-		val = alertpanel_full(_("Notice"), msg, GTK_STOCK_NO, GTK_STOCK_YES,
-		      		      NULL, ALERTFOCUS_FIRST, FALSE, NULL,
-										ALERT_WARNING);
-			
+			   "process id: %d"), pid);
+		val = alertpanel_full(_("Notice"), msg, GTK_STOCK_NO,
+				      GTK_STOCK_YES, NULL, ALERTFOCUS_FIRST,
+				      FALSE, NULL, ALERT_WARNING);
 		g_free(msg);
 
 		if (val == G_ALERTALTERNATE) {
 			g_source_remove(compose->exteditor_tag);
-			g_io_channel_shutdown(compose->exteditor_ch,
-					      FALSE, NULL);
-			g_io_channel_unref(compose->exteditor_ch);
 
-			if (kill(pgid, SIGTERM) < 0) perror("kill");
+#ifdef G_OS_WIN32
+			if (!TerminateProcess(compose->exteditor_pid, 0))
+				perror("TerminateProcess");
+#else
+			if (kill(pid, SIGTERM) < 0) perror("kill");
 			waitpid(compose->exteditor_pid, NULL, 0);
+#endif /* G_OS_WIN32 */
 
-			g_warning("Terminated process group id: %d. "
-				  "Temporary file: %s", -pgid, compose->exteditor_file);
+			g_warning("Terminated process id: %d. "
+				  "Temporary file: %s", pid, compose->exteditor_file);
+			g_spawn_close_pid(compose->exteditor_pid);
 
 			compose_set_ext_editor_sensitive(compose, TRUE);
 
 			g_free(compose->exteditor_file);
 			compose->exteditor_file    = NULL;
 			compose->exteditor_pid     = -1;
-			compose->exteditor_ch      = NULL;
 			compose->exteditor_tag     = -1;
 		} else
 			return FALSE;
@@ -9841,75 +9842,6 @@ static gboolean compose_ext_editor_kill(Compose *compose)
 	return TRUE;
 }
 
-static gboolean compose_input_cb(GIOChannel *source, GIOCondition condition,
-				 gpointer data)
-{
-	gchar buf[3] = "3";
-	Compose *compose = (Compose *)data;
-	gsize bytes_read;
-
-	debug_print("Compose: input from monitoring process\n");
-
-	if (g_io_channel_read_chars(source, buf, sizeof(buf), &bytes_read, NULL) != G_IO_STATUS_NORMAL) {
-		bytes_read = 0;
-		buf[0] = '\0';
-	}
-
-	g_io_channel_shutdown(source, FALSE, NULL);
-	g_io_channel_unref(source);
-
-	waitpid(compose->exteditor_pid, NULL, 0);
-
-	if (buf[0] == '0') {		/* success */
-		GtkTextView *text = GTK_TEXT_VIEW(compose->text);
-		GtkTextBuffer *buffer = gtk_text_view_get_buffer(text);
-		GtkTextIter start, end;
-		gchar *chars;
-
-		gtk_text_buffer_set_text(buffer, "", -1);
-		compose_insert_file(compose, compose->exteditor_file);
-		compose_changed_cb(NULL, compose);
-
-		/* Check if we should save the draft or not */
-		if (compose_can_autosave(compose))
-		  compose_draft((gpointer)compose, COMPOSE_AUTO_SAVE);
-
-		if (claws_unlink(compose->exteditor_file) < 0)
-			FILE_OP_ERROR(compose->exteditor_file, "unlink");
-
-		buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(compose->text));
-		gtk_text_buffer_get_start_iter(buffer, &start);
-		gtk_text_buffer_get_end_iter(buffer, &end);
-		chars = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
-		if (chars && strlen(chars) > 0)
-			compose->modified = TRUE;
-		g_free(chars);
-	} else if (buf[0] == '1') {	/* failed */
-		g_warning("Couldn't exec external editor");
-		if (claws_unlink(compose->exteditor_file) < 0)
-			FILE_OP_ERROR(compose->exteditor_file, "unlink");
-	} else if (buf[0] == '2') {
-		g_warning("Couldn't write to file");
-	} else if (buf[0] == '3') {
-		g_warning("Pipe read failed");
-	}
-
-	compose_set_ext_editor_sensitive(compose, TRUE);
-
-	g_free(compose->exteditor_file);
-	compose->exteditor_file    = NULL;
-	compose->exteditor_pid     = -1;
-	compose->exteditor_ch      = NULL;
-	compose->exteditor_tag     = -1;
-	if (compose->exteditor_socket) {
-		gtk_widget_destroy(compose->exteditor_socket);
-		compose->exteditor_socket = NULL;
-	}
-
-
-	return FALSE;
-}
-
 static char *ext_editor_menu_entries[] = {
 	"Menu/Message/Send",
 	"Menu/Message/SendLater",
@@ -9991,7 +9923,6 @@ static gboolean compose_ext_editor_plug_removed_cb(GtkSocket *socket, Compose *c
 	/* returning FALSE allows destruction of the socket */
 	return FALSE;
 }
-#endif /* G_OS_UNIX */
 
 /**
  * compose_undo_state_changed:
@@ -10759,12 +10690,10 @@ static void compose_close_cb(GtkAction *action, gpointer data)
 	Compose *compose = (Compose *)data;
 	AlertValue val;
 
-#ifdef G_OS_UNIX
 	if (compose->exteditor_tag != -1) {
 		if (!compose_ext_editor_kill(compose))
 			return;
 	}
-#endif
 
 	if (compose->modified) {
 		gboolean reedit = (compose->rmode == COMPOSE_REEDIT);
@@ -10871,12 +10800,10 @@ static void compose_ext_editor_cb(GtkAction *action, gpointer data)
 {
 	Compose *compose = (Compose *)data;
 
-#ifdef G_OS_UNIX
 	if (compose->exteditor_tag != -1) {
 		debug_print("ignoring open external editor: external editor still open\n");
 		return;
 	}
-#endif
 	compose_exec_ext_editor(compose);
 }
 
diff --git a/src/compose.h b/src/compose.h
index 6fd032a4a..3c155be55 100644
--- a/src/compose.h
+++ b/src/compose.h
@@ -222,8 +222,7 @@ struct _Compose
 
 	/* external editor */
 	gchar      *exteditor_file;
-	pid_t       exteditor_pid;
-	GIOChannel *exteditor_ch;
+	GPid        exteditor_pid;
 	gint        exteditor_tag;
 	GtkWidget  *exteditor_socket;
 

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list