[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