aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorRobin Haberkorn <rhaberkorn@fmsbw.de>2026-01-24 16:29:23 +0100
committerRobin Haberkorn <rhaberkorn@fmsbw.de>2026-01-24 16:37:27 +0100
commit7ff541040edc3b3f8a25bb69e04ecb57cba12954 (patch)
tree36e3e6fd6edca9f05f0e6afe193f0f241c305907 /src
parent54858904a67e683483bdfb33c08fe9941ab16cf4 (diff)
GTK: fixed --detach and support stdout/stderr redirections
* We fork after command line arguments have been parsed, which is after gtk_get_option_group() has been called. This means that GTK was already initialized and it wasn't safe to continue after forking. * As a workaround, we now re-exec with the original argv array, so GTK can be properly reinitialized. Since we did not remove `--detach` from argv (and that would be nontrivial), it would fork again endlessly, so we use an environment variable $__SCITECO_DETACHED to guard against recursive forks. * Also, do not close stdin/stdout/stderr if has been redirected to a file, so you can now e.g. call `gsciteco -d >some-file`. * This was broken since v2.5.0.
Diffstat (limited to 'src')
-rw-r--r--src/interface-curses/interface.c2
-rw-r--r--src/interface-gtk/interface.c31
-rw-r--r--src/interface.h2
-rw-r--r--src/main.c2
4 files changed, 29 insertions, 8 deletions
diff --git a/src/interface-curses/interface.c b/src/interface-curses/interface.c
index 6c8b231..365a096 100644
--- a/src/interface-curses/interface.c
+++ b/src/interface-curses/interface.c
@@ -443,7 +443,7 @@ static void teco_interface_set_window_title(const gchar *title);
static void teco_interface_draw_info(void);
void
-teco_interface_init(void)
+teco_interface_init(gint argc, gchar **argv)
{
for (guint i = 0; i < G_N_ELEMENTS(teco_interface.color_table); i++)
teco_interface.color_table[i] = -1;
diff --git a/src/interface-gtk/interface.c b/src/interface-gtk/interface.c
index ace3a2f..08ccf5d 100644
--- a/src/interface-gtk/interface.c
+++ b/src/interface-gtk/interface.c
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <signal.h>
+#include <unistd.h>
#include <glib.h>
#include <glib/gprintf.h>
@@ -132,10 +133,10 @@ static struct {
} teco_interface;
void
-teco_interface_init(void)
+teco_interface_init(gint argc, gchar **argv)
{
#ifdef G_OS_UNIX
- if (teco_interface.detach) {
+ if (teco_interface.detach && !g_getenv("__SCITECO_DETACHED")) {
/*
* NOTE: There is also daemon() on BSD/Linux,
* but the following should be more portable.
@@ -148,9 +149,29 @@ teco_interface_init(void)
setsid();
- g_freopen("/dev/null", "r", stdin);
- g_freopen("/dev/null", "a+", stdout);
- g_freopen("/dev/null", "a+", stderr);
+ if (isatty(0)) {
+ G_GNUC_UNUSED FILE *stdin_new = g_freopen("/dev/null", "r", stdin);
+ g_assert(stdin_new != NULL);
+ }
+ if (isatty(1)) {
+ G_GNUC_UNUSED FILE *stdout_new = g_freopen("/dev/null", "a+", stdout);
+ g_assert(stdout_new != NULL);
+ }
+ if (isatty(2)) {
+ G_GNUC_UNUSED FILE *stderr_new = g_freopen("/dev/null", "a+", stderr);
+ g_assert(stderr_new != NULL);
+ }
+
+ /*
+ * gtk_get_option_group() already initialized GTK and even though the
+ * display is not yet opened, it's unsafe to continue.
+ * Instead, we re-exec already in the child process.
+ * We cannot easily remove --detach from argv, but still guard against
+ * recursive forks by using an environment variable.
+ */
+ g_setenv("__SCITECO_DETACHED", "1", TRUE);
+ execv(argv[0], argv);
+ g_assert_not_reached();
}
#endif
diff --git a/src/interface.h b/src/interface.h
index f196a83..54f807b 100644
--- a/src/interface.h
+++ b/src/interface.h
@@ -51,7 +51,7 @@
extern teco_view_t *teco_interface_current_view;
/** @pure */
-void teco_interface_init(void);
+void teco_interface_init(gint argc, gchar **argv);
/** @pure */
GOptionGroup *teco_interface_get_options(void);
diff --git a/src/main.c b/src/main.c
index 4d46817..0023c78 100644
--- a/src/main.c
+++ b/src/main.c
@@ -445,7 +445,7 @@ main(int argc, char **argv)
*/
teco_qreg_table_init(&teco_qreg_table_globals, TRUE);
- teco_interface_init();
+ teco_interface_init(argc, argv);
/*
* QRegister view must be initialized only now