summaryrefslogtreecommitdiffstats
path: root/debian/patches/Provide-fallback-for-reading-current-directory-if-OS.patch
blob: 887697716c9e5fa3a5aba9ec18fa8d5180d9b9ec (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
From: Martin Pitt <martinpitt@gnome.org>
Date: Sun, 31 May 2015 17:09:28 +0000
Subject: Provide fallback for reading current directory if OSC 7 fails

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=697475
Bug-Debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=712628
---
 src/terminal-screen.cc | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/src/terminal-screen.cc b/src/terminal-screen.cc
index 54e1022..943e0ef 100644
--- a/src/terminal-screen.cc
+++ b/src/terminal-screen.cc
@@ -358,6 +358,63 @@ terminal_screen_clear_exec_data (TerminalScreen *screen,
 
 G_DEFINE_TYPE (TerminalScreen, terminal_screen, VTE_TYPE_TERMINAL)
 
+static char *
+cwd_of_pid (int pid)
+{
+  static const char patterns[][18] = {
+    "/proc/%d/cwd",         /* Linux */
+    "/proc/%d/path/cwd",    /* Solaris >= 10 */
+  };
+  guint i;
+
+  if (pid == -1)
+    return nullptr;
+
+  /* Try to get the working directory using various OS-specific mechanisms */
+  for (i = 0; i < G_N_ELEMENTS (patterns); ++i)
+    {
+      char cwd_file[64];
+      char buf[PATH_MAX + 1];
+      int len;
+
+      /* disable "format not a string literal" error, we know what we are doing */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+      g_snprintf (cwd_file, sizeof (cwd_file), patterns[i], pid);
+#pragma GCC diagnostic pop
+      len = readlink (cwd_file, buf, sizeof (buf) - 1);
+
+      if (len > 0 && buf[0] == '/')
+        return g_strndup (buf, len);
+
+      /* If that didn't do it, try this hack */
+      if (len <= 0)
+        {
+          char *cwd, *working_dir = NULL;
+
+          cwd = g_get_current_dir ();
+          if (cwd != NULL)
+            {
+              /* On Solaris, readlink returns an empty string, but the
+               * link can be used as a directory, including as a target
+               * of chdir().
+               */
+              if (chdir (cwd_file) == 0)
+                {
+                  working_dir = g_get_current_dir ();
+                  (void) chdir (cwd);
+                }
+              g_free (cwd);
+            }
+
+          if (working_dir)
+            return working_dir;
+        }
+    }
+
+  return nullptr;
+}
+
 static void
 free_tag_data (TagData *tagdata)
 {
@@ -1830,12 +1887,21 @@ terminal_screen_button_press (GtkWidget      *widget,
 char *
 terminal_screen_get_current_dir (TerminalScreen *screen)
 {
+  TerminalScreenPrivate *priv = screen->priv;
   const char *uri;
 
   uri = vte_terminal_get_current_directory_uri (VTE_TERMINAL (screen));
   if (uri != nullptr)
     return g_filename_from_uri (uri, nullptr, nullptr);
 
+  if (priv->child_pid > 0) {
+    char *cwd = cwd_of_pid (priv->child_pid);
+    if (cwd != NULL) {
+      g_debug ("terminal_screen_get_current_dir: VTE current dir n/a, reading from /proc: %s", cwd);
+      return cwd;
+    }
+  }
+
   ExecData *data = screen->priv->exec_data;
   if (data && data->cwd)
     return g_strdup (data->cwd);