Blob Blame Raw
diff --git a/src/terminal-screen.c b/src/terminal-screen.c
index e6dd61e..10deb3f 100644
--- a/src/terminal-screen.c
+++ b/src/terminal-screen.c
@@ -183,6 +183,59 @@ static guint n_skey_regexes;
 
 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 NULL;
+
+  /* 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;
+
+      g_snprintf (cwd_file, sizeof (cwd_file), patterns[i], pid);
+      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 ();
+                  chdir (cwd);
+                }
+              g_free (cwd);
+            }
+
+          if (working_dir)
+            return working_dir;
+        }
+    }
+
+  return NULL;
+}
+
 static void
 free_tag_data (TagData *tagdata)
 {
@@ -1738,75 +1791,57 @@ terminal_screen_get_dynamic_icon_title (TerminalScreen *screen)
  * terminal_screen_get_current_dir:
  * @screen:
  *
- * Returns: a newly allocated string containing the current working directory
- *   of the foreground process in @screen's PTY; or otherwise the initial working
- *   directory as set by terminal_screen_new()
+ * Tries to determine the current working directory of the foreground process
+ * in @screen's PTY, falling back to the current working directory of the
+ * primary child.
+ * 
+ * Returns: a newly allocated string containing the current working directory,
+ *   or %NULL on failure
  */
 char*
 terminal_screen_get_current_dir (TerminalScreen *screen)
 {
-  static const char patterns[][18] = {
-    "/proc/%d/cwd",         /* Linux */
-    "/proc/%d/path/cwd",    /* Solaris >= 10 */
-  };
   TerminalScreenPrivate *priv = screen->priv;
-  int fgpid;
-  guint i;
-  
-  g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), NULL);
+  char *cwd;
+
+  if (priv->pty_fd != -1) {
+    /* Get the foreground process ID */
+    cwd = cwd_of_pid (tcgetpgrp (priv->pty_fd));
+    if (cwd != NULL)
+      return cwd;
+
+    /* If that didn't work, try falling back to the primary child. See bug #575184. */
+    cwd = cwd_of_pid (priv->child_pid);
+    if (cwd != NULL)
+      return cwd;
+  }
 
-  if (priv->pty_fd == -1)
-    return g_strdup (priv->initial_working_directory);
+  return NULL;
+}
 
-  /* Get the foreground process ID */
-  fgpid = tcgetpgrp (priv->pty_fd);
+/**
+ * terminal_screen_get_current_dir_with_fallback:
+ * @screen:
+ *
+ * Returns: a newly allocated string containing the current working directory
+ *   of the foreground process in @screen's PTY; or otherwise the initial working
+ *   directory as set by terminal_screen_new(), or %NULL if unable to determine
+ *   the current working directory
+ */
+char*
+terminal_screen_get_current_dir_with_fallback (TerminalScreen *screen)
+{
+  TerminalScreenPrivate *priv = screen->priv;
+  char *cwd;
 
-  /* If that didn't work, try falling back to the primary child. See bug #575184. */
-  if (fgpid == -1)
-    fgpid = priv->child_pid;
+  cwd = terminal_screen_get_current_dir (screen);
+  if (cwd != NULL)
+    return cwd;
 
-  if (fgpid == -1)
+  if (priv->initial_working_directory != NULL)
     return g_strdup (priv->initial_working_directory);
 
-  /* 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;
-
-      g_snprintf (cwd_file, sizeof (cwd_file), patterns[i], fgpid);
-      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 ();
-                  chdir (cwd);
-                }
-              g_free (cwd);
-            }
-
-          if (working_dir)
-            return working_dir;
-        }
-    }
-
-  return g_strdup (priv->initial_working_directory);
+  return g_strdup (g_get_home_dir ());
 }
 
 void
diff --git a/src/terminal-screen.h b/src/terminal-screen.h
index efd5b3c..8b1e422 100644
--- a/src/terminal-screen.h
+++ b/src/terminal-screen.h
@@ -110,6 +110,7 @@ const char *terminal_screen_get_dynamic_title      (TerminalScreen *screen);
 const char *terminal_screen_get_dynamic_icon_title (TerminalScreen *screen);
 
 char *terminal_screen_get_current_dir (TerminalScreen *screen);
+char *terminal_screen_get_current_dir_with_fallback (TerminalScreen *screen);
 
 void        terminal_screen_set_font (TerminalScreen *screen);
 void        terminal_screen_set_font_scale    (TerminalScreen *screen,
diff --git a/src/terminal-window.c b/src/terminal-window.c
index 188bdd1..05e0af1 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -2807,7 +2807,7 @@ file_new_window_callback (GtkAction *action,
 
   new_window = terminal_app_new_window (app, gtk_widget_get_screen (GTK_WIDGET (window)));
 
-  new_working_directory = terminal_screen_get_current_dir (priv->active_screen);
+  new_working_directory = terminal_screen_get_current_dir_with_fallback (priv->active_screen);
   terminal_app_new_terminal (app, new_window, profile,
                              NULL, NULL,
                              new_working_directory,
@@ -2839,7 +2839,7 @@ file_new_tab_callback (GtkAction *action,
   if (_terminal_profile_get_forgotten (profile))
     return;
 
-  new_working_directory = terminal_screen_get_current_dir (priv->active_screen);
+  new_working_directory = terminal_screen_get_current_dir_with_fallback (priv->active_screen);
   terminal_app_new_terminal (app, window, profile,
                              NULL, NULL,
                              new_working_directory,