Blame fish-upstream-CVE-2014-2905.patch

Andy Lutomirski 4de0b6
From 4cb4fc3ef889788b9755451bc565e27bb803b8ba Mon Sep 17 00:00:00 2001
Andy Lutomirski 4de0b6
Message-Id: <4cb4fc3ef889788b9755451bc565e27bb803b8ba.1407803923.git.luto@amacapital.net>
Andy Lutomirski 8e15cc
From: David Adam <zanchey@ucc.gu.uwa.edu.au>
Andy Lutomirski 4de0b6
Date: Sun, 20 Apr 2014 19:20:07 +0800
Andy Lutomirski 4de0b6
Subject: [PATCH] Fix for CVE-2014-2905 - fishd restart required.
Andy Lutomirski 8e15cc
Andy Lutomirski 4de0b6
 - Use a secure path for sockets (some code used under license from
Andy Lutomirski 4de0b6
   tmux).
Andy Lutomirski 4de0b6
 - Provide the secure path in the environment as $__fish_runtime_dir.
Andy Lutomirski 4de0b6
 - Link the new path to the old path to ease migration from earlier
Andy Lutomirski 4de0b6
   versions.
Andy Lutomirski 8e15cc
Andy Lutomirski 4de0b6
Closes #1359.
Andy Lutomirski 4de0b6
Andy Lutomirski 4de0b6
After installing fish built from or after this commit, you MUST
Andy Lutomirski 4de0b6
terminate all running fishd processes (`killall fishd`, `pkill fishd`
Andy Lutomirski 4de0b6
or similar). Distributors are encouraged to do this from within their
Andy Lutomirski 4de0b6
packaging scripts. fishd will restart automatically, and no data should
Andy Lutomirski 4de0b6
be lost.
Andy Lutomirski 8e15cc
---
Andy Lutomirski 4de0b6
 common.cpp               | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
Andy Lutomirski 4de0b6
 common.h                 |  2 ++
Andy Lutomirski 4de0b6
 doc_src/license.hdr      | 20 ++++++++++++++
Andy Lutomirski 4de0b6
 env.cpp                  |  7 ++---
Andy Lutomirski 4de0b6
 env_universal.cpp        | 41 +++++-----------------------
Andy Lutomirski 4de0b6
 env_universal.h          |  2 +-
Andy Lutomirski 4de0b6
 env_universal_common.cpp | 10 +++++--
Andy Lutomirski 4de0b6
 env_universal_common.h   |  9 +++++--
Andy Lutomirski 4de0b6
 fish_pager.cpp           |  2 +-
Andy Lutomirski 4de0b6
 fishd.cpp                | 56 +++++++++++++++++++++++++++++++++++---
Andy Lutomirski 4de0b6
 10 files changed, 172 insertions(+), 47 deletions(-)
Andy Lutomirski 8e15cc
Andy Lutomirski 4de0b6
diff --git a/common.cpp b/common.cpp
Andy Lutomirski 4de0b6
index 7a9f7a5..3e5a2c8 100644
Andy Lutomirski 4de0b6
--- a/common.cpp
Andy Lutomirski 4de0b6
+++ b/common.cpp
Andy Lutomirski 4de0b6
@@ -24,6 +24,7 @@ parts of fish.
Andy Lutomirski 4de0b6
 #include <stdio.h>
Andy Lutomirski 4de0b6
 #include <dirent.h>
Andy Lutomirski 4de0b6
 #include <sys/types.h>
Andy Lutomirski 4de0b6
+#include <pwd.h>
Andy Lutomirski 8e15cc
 
Andy Lutomirski 4de0b6
 #ifdef HAVE_SYS_IOCTL_H
Andy Lutomirski 4de0b6
 #include <sys/ioctl.h>
Andy Lutomirski 4de0b6
@@ -2342,3 +2343,72 @@ char **make_null_terminated_array(const std::vector<std::string> &lst)
Andy Lutomirski 4de0b6
 {
Andy Lutomirski 4de0b6
     return make_null_terminated_array_helper(lst);
Andy Lutomirski 4de0b6
 }
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
+/**
Andy Lutomirski 4de0b6
+   Check, and create if necessary, a secure runtime path
Andy Lutomirski 4de0b6
+   Derived from tmux.c in tmux (http://tmux.sourceforge.net/)
Andy Lutomirski 4de0b6
+*/
Andy Lutomirski 4de0b6
+static int check_runtime_path(const char * path)
Andy Lutomirski 4de0b6
+{
Andy Lutomirski 4de0b6
+    /*
Andy Lutomirski 4de0b6
+     * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
Andy Lutomirski 4de0b6
+     *
Andy Lutomirski 4de0b6
+     * Permission to use, copy, modify, and distribute this software for any
Andy Lutomirski 4de0b6
+     * purpose with or without fee is hereby granted, provided that the above
Andy Lutomirski 4de0b6
+     * copyright notice and this permission notice appear in all copies.
Andy Lutomirski 4de0b6
+     *
Andy Lutomirski 4de0b6
+     * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
Andy Lutomirski 4de0b6
+     * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
Andy Lutomirski 4de0b6
+     * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
Andy Lutomirski 4de0b6
+     * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
Andy Lutomirski 4de0b6
+     * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
Andy Lutomirski 4de0b6
+     * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
Andy Lutomirski 4de0b6
+     * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Andy Lutomirski 4de0b6
+     */
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
+    struct stat statpath;
Andy Lutomirski 4de0b6
+    u_int uid = geteuid();
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
+    if (mkdir(path, S_IRWXU) != 0 && errno != EEXIST)
Andy Lutomirski 4de0b6
+        return errno;
Andy Lutomirski 4de0b6
+    if (lstat(path, &statpath) != 0)
Andy Lutomirski 4de0b6
+        return errno;
Andy Lutomirski 4de0b6
+    if (!S_ISDIR(statpath.st_mode)
Andy Lutomirski 4de0b6
+            || statpath.st_uid != uid
Andy Lutomirski 4de0b6
+            || (statpath.st_mode & (S_IRWXG|S_IRWXO)) != 0)
Andy Lutomirski 4de0b6
+        return EACCES;
Andy Lutomirski 4de0b6
+    return 0;
Andy Lutomirski 4de0b6
+}
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
+/** Return the path of an appropriate runtime data directory */
Andy Lutomirski 4de0b6
+const char* common_get_runtime_path(void)
Andy Lutomirski 4de0b6
+{
Andy Lutomirski 4de0b6
+    const char *dir = getenv("XDG_RUNTIME_DIR");
Andy Lutomirski 4de0b6
+    const char *uname = getenv("USER");
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
+    if (uname == NULL)
Andy Lutomirski 4de0b6
+    {
Andy Lutomirski 4de0b6
+        const struct passwd *pw = getpwuid(getuid());
Andy Lutomirski 4de0b6
+        uname = pw->pw_name;
Andy Lutomirski 4de0b6
+    }
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
+    if (dir == NULL)
Andy Lutomirski 4de0b6
+    {
Andy Lutomirski 4de0b6
+        // /tmp/fish.user
Andy Lutomirski 4de0b6
+        dir = "/tmp/fish.";
Andy Lutomirski 4de0b6
+        std::string path;
Andy Lutomirski 4de0b6
+        path.reserve(strlen(dir) + strlen(uname));
Andy Lutomirski 4de0b6
+        path.append(dir);
Andy Lutomirski 4de0b6
+        path.append(uname);
Andy Lutomirski 4de0b6
+        if (check_runtime_path(path.c_str()) != 0)
Andy Lutomirski 4de0b6
+        {
Andy Lutomirski 4de0b6
+            debug(0, L"Couldn't create secure runtime path: '%s'", path.c_str());
Andy Lutomirski 4de0b6
+            exit(EXIT_FAILURE);
Andy Lutomirski 4de0b6
+        }
Andy Lutomirski 4de0b6
+        return strdup(path.c_str());
Andy Lutomirski 4de0b6
+    }
Andy Lutomirski 4de0b6
+    else
Andy Lutomirski 4de0b6
+    {
Andy Lutomirski 4de0b6
+        return dir;
Andy Lutomirski 4de0b6
+    }
Andy Lutomirski 4de0b6
+}
Andy Lutomirski 4de0b6
diff --git a/common.h b/common.h
Andy Lutomirski 4de0b6
index 57fe7fa..4d18aca 100644
Andy Lutomirski 4de0b6
--- a/common.h
Andy Lutomirski 4de0b6
+++ b/common.h
Andy Lutomirski 4de0b6
@@ -813,5 +813,7 @@ extern "C" {
Andy Lutomirski 4de0b6
     __attribute__((noinline)) void debug_thread_error(void);
Andy Lutomirski 4de0b6
 }
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
+/** Return the path of an appropriate runtime data directory */
Andy Lutomirski 4de0b6
+const char* common_get_runtime_path(void);
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 #endif
Andy Lutomirski 4de0b6
diff --git a/doc_src/license.hdr b/doc_src/license.hdr
Andy Lutomirski 4de0b6
index 64bab10..76981a9 100644
Andy Lutomirski 4de0b6
--- a/doc_src/license.hdr
Andy Lutomirski 4de0b6
+++ b/doc_src/license.hdr
Andy Lutomirski 4de0b6
@@ -1400,6 +1400,26 @@ POSSIBILITY OF SUCH DAMAGES.
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 

Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
+

License for code derived from tmux

Andy Lutomirski 4de0b6
+
Andy Lutomirski 4de0b6
+Fish contains code derived from
Andy Lutomirski 4de0b6
+tmux, made available under an ISC
Andy Lutomirski 4de0b6
+license.
Andy Lutomirski 4de0b6
+

Andy Lutomirski 4de0b6
+Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
Andy Lutomirski 4de0b6
+

Andy Lutomirski 4de0b6
+Permission to use, copy, modify, and distribute this software for any
Andy Lutomirski 4de0b6
+purpose with or without fee is hereby granted, provided that the above
Andy Lutomirski 4de0b6
+copyright notice and this permission notice appear in all copies.
Andy Lutomirski 4de0b6
+

Andy Lutomirski 4de0b6
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
Andy Lutomirski 4de0b6
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
Andy Lutomirski 4de0b6
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
Andy Lutomirski 4de0b6
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
Andy Lutomirski 4de0b6
+WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
Andy Lutomirski 4de0b6
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
Andy Lutomirski 4de0b6
+OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
 */
Andy Lutomirski 8e15cc
 
Andy Lutomirski 8e15cc
 \htmlonly  \endhtmlonly
Andy Lutomirski 4de0b6
diff --git a/env.cpp b/env.cpp
Andy Lutomirski 4de0b6
index 13f87b6..0bda417 100644
Andy Lutomirski 4de0b6
--- a/env.cpp
Andy Lutomirski 4de0b6
+++ b/env.cpp
Andy Lutomirski 4de0b6
@@ -57,7 +57,7 @@
Andy Lutomirski 4de0b6
 #include "complete.h"
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 /** Command used to start fishd */
Andy Lutomirski 4de0b6
-#define FISHD_CMD L"fishd ^ /tmp/fishd.log.%s"
Andy Lutomirski 4de0b6
+#define FISHD_CMD L"fishd ^ $__fish_runtime_dir/fishd.log.%s"
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 // Version for easier debugging
Andy Lutomirski 4de0b6
 //#define FISHD_CMD L"fishd"
Andy Lutomirski 4de0b6
@@ -618,10 +618,11 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
Andy Lutomirski 4de0b6
     env_set(L"version", version.c_str(), ENV_GLOBAL);
Andy Lutomirski 4de0b6
     env_set(L"FISH_VERSION", version.c_str(), ENV_GLOBAL);
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
-    const env_var_t fishd_dir_wstr = env_get_string(L"FISHD_SOCKET_DIR");
Andy Lutomirski 4de0b6
     const env_var_t user_dir_wstr = env_get_string(L"USER");
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
-    wchar_t * fishd_dir = fishd_dir_wstr.missing()?NULL:const_cast<wchar_t*>(fishd_dir_wstr.c_str());
Andy Lutomirski 4de0b6
+    const char * fishd_dir = common_get_runtime_path();
Andy Lutomirski 4de0b6
+    env_set(L"__fish_runtime_dir", str2wcstring(fishd_dir).c_str(), ENV_GLOBAL);
Andy Lutomirski 4de0b6
+
Andy Lutomirski 4de0b6
     wchar_t * user_dir = user_dir_wstr.missing()?NULL:const_cast<wchar_t*>(user_dir_wstr.c_str());
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
     env_universal_init(fishd_dir , user_dir ,
Andy Lutomirski 8e15cc
diff --git a/env_universal.cpp b/env_universal.cpp
Andy Lutomirski 4de0b6
index c7d060a..1a97443 100644
Andy Lutomirski 8e15cc
--- a/env_universal.cpp
Andy Lutomirski 8e15cc
+++ b/env_universal.cpp
Andy Lutomirski 4de0b6
@@ -61,7 +61,7 @@ static int get_socket_count = 0;
Andy Lutomirski 4de0b6
 #define DEFAULT_RETRY_COUNT 15
Andy Lutomirski 4de0b6
 #define DEFAULT_RETRY_DELAY 0.2
Andy Lutomirski 8e15cc
 
Andy Lutomirski 4de0b6
-static wchar_t * path;
Andy Lutomirski 4de0b6
+static const char * path;
Andy Lutomirski 4de0b6
 static wchar_t *user;
Andy Lutomirski 4de0b6
 static void (*start_fishd)();
Andy Lutomirski 4de0b6
 static void (*external_callback)(fish_message_type_t type, const wchar_t *name, const wchar_t *val);
Andy Lutomirski 4de0b6
@@ -82,48 +82,19 @@ static int try_get_socket_once(void)
Andy Lutomirski 4de0b6
 {
Andy Lutomirski 4de0b6
     int s;
Andy Lutomirski 8e15cc
 
Andy Lutomirski 4de0b6
-    wchar_t *wdir;
Andy Lutomirski 4de0b6
-    wchar_t *wuname;
Andy Lutomirski 4de0b6
-    char *dir = 0;
Andy Lutomirski 4de0b6
-
Andy Lutomirski 4de0b6
-    wdir = path;
Andy Lutomirski 4de0b6
-    wuname = user;
Andy Lutomirski 4de0b6
-
Andy Lutomirski 8e15cc
     if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
Andy Lutomirski 8e15cc
     {
Andy Lutomirski 4de0b6
         wperror(L"socket");
Andy Lutomirski 8e15cc
         return -1;
Andy Lutomirski 8e15cc
     }
Andy Lutomirski 8e15cc
 
Andy Lutomirski 4de0b6
-    if (wdir)
Andy Lutomirski 4de0b6
-        dir = wcs2str(wdir);
Andy Lutomirski 4de0b6
-    else
Andy Lutomirski 4de0b6
-        dir = strdup("/tmp");
Andy Lutomirski 4de0b6
-
Andy Lutomirski 4de0b6
-    std::string uname;
Andy Lutomirski 4de0b6
-    if (wuname)
Andy Lutomirski 4de0b6
-    {
Andy Lutomirski 4de0b6
-        uname = wcs2string(wuname);
Andy Lutomirski 4de0b6
-    }
Andy Lutomirski 4de0b6
-    else
Andy Lutomirski 4de0b6
-    {
Andy Lutomirski 4de0b6
-        struct passwd *pw = getpwuid(getuid());
Andy Lutomirski 4de0b6
-        if (pw && pw->pw_name)
Andy Lutomirski 4de0b6
-        {
Andy Lutomirski 4de0b6
-            uname = pw->pw_name;
Andy Lutomirski 4de0b6
-        }
Andy Lutomirski 4de0b6
-    }
Andy Lutomirski 4de0b6
-
Andy Lutomirski 4de0b6
     std::string name;
Andy Lutomirski 4de0b6
-    name.reserve(strlen(dir) + uname.size() + strlen(SOCK_FILENAME) + 2);
Andy Lutomirski 4de0b6
-    name.append(dir);
Andy Lutomirski 4de0b6
-    name.append("/");
Andy Lutomirski 4de0b6
+    name.reserve(strlen(path) + strlen(SOCK_FILENAME) + 1);
Andy Lutomirski 4de0b6
+    name.append(path);
Andy Lutomirski 4de0b6
+    name.push_back('/');
Andy Lutomirski 4de0b6
     name.append(SOCK_FILENAME);
Andy Lutomirski 4de0b6
-    name.append(uname);
Andy Lutomirski 4de0b6
-
Andy Lutomirski 4de0b6
-    free(dir);
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
-    debug(3, L"Connect to socket %s at fd %2", name.c_str(), s);
Andy Lutomirski 4de0b6
+    debug(3, L"Connect to socket %s at fd %d", name.c_str(), s);
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
     struct sockaddr_un local = {};
Andy Lutomirski 4de0b6
     local.sun_family = AF_UNIX;
Andy Lutomirski 4de0b6
@@ -271,7 +242,7 @@ static void reconnect()
Andy Lutomirski 8e15cc
 }
Andy Lutomirski 8e15cc
 
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
-void env_universal_init(wchar_t * p,
Andy Lutomirski 4de0b6
+void env_universal_init(const char * p,
Andy Lutomirski 4de0b6
                         wchar_t *u,
Andy Lutomirski 4de0b6
                         void (*sf)(),
Andy Lutomirski 4de0b6
                         void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val))
Andy Lutomirski 4de0b6
diff --git a/env_universal.h b/env_universal.h
Andy Lutomirski 4de0b6
index 4f38fe7..9e6ab85 100644
Andy Lutomirski 4de0b6
--- a/env_universal.h
Andy Lutomirski 4de0b6
+++ b/env_universal.h
Andy Lutomirski 4de0b6
@@ -17,7 +17,7 @@ extern connection_t env_universal_server;
Andy Lutomirski 4de0b6
 /**
Andy Lutomirski 4de0b6
    Initialize the envuni library
Andy Lutomirski 4de0b6
 */
Andy Lutomirski 4de0b6
-void env_universal_init(wchar_t * p,
Andy Lutomirski 4de0b6
+void env_universal_init(const char * p,
Andy Lutomirski 4de0b6
                         wchar_t *u,
Andy Lutomirski 4de0b6
                         void (*sf)(),
Andy Lutomirski 4de0b6
                         void (*cb)(fish_message_type_t type, const wchar_t *name, const wchar_t *val));
Andy Lutomirski 4de0b6
diff --git a/env_universal_common.cpp b/env_universal_common.cpp
Andy Lutomirski 4de0b6
index f600e70..2b12cf1 100644
Andy Lutomirski 4de0b6
--- a/env_universal_common.cpp
Andy Lutomirski 4de0b6
+++ b/env_universal_common.cpp
Andy Lutomirski 4de0b6
@@ -27,7 +27,6 @@
Andy Lutomirski 4de0b6
 #include <locale.h>
Andy Lutomirski 4de0b6
 #include <dirent.h>
Andy Lutomirski 4de0b6
 #include <signal.h>
Andy Lutomirski 4de0b6
-#include <sys/stat.h>
Andy Lutomirski 4de0b6
 #include <map>
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 #ifdef HAVE_SYS_SELECT_H
Andy Lutomirski 4de0b6
@@ -87,6 +86,13 @@
Andy Lutomirski 4de0b6
 #define ENV_UNIVERSAL_EOF   0x102
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 /**
Andy Lutomirski 4de0b6
+   Maximum length of socket filename
Andy Lutomirski 4de0b6
+*/
Andy Lutomirski 4de0b6
+#ifndef UNIX_PATH_MAX
Andy Lutomirski 4de0b6
+#define UNIX_PATH_MAX 100
Andy Lutomirski 8e15cc
+#endif
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
+/**
Andy Lutomirski 4de0b6
    A variable entry. Stores the value of a variable and whether it
Andy Lutomirski 4de0b6
    should be exported. Obviously, it needs to be allocated large
Andy Lutomirski 4de0b6
    enough to fit the value string.
Andy Lutomirski 4de0b6
@@ -417,7 +423,7 @@ void env_universal_common_init(void (*cb)(fish_message_type_t type, const wchar_
Andy Lutomirski 4de0b6
 }
Andy Lutomirski 8e15cc
 
Andy Lutomirski 4de0b6
 /**
Andy Lutomirski 4de0b6
-   Read one byte of date form the specified connection
Andy Lutomirski 4de0b6
+   Read one byte of date from the specified connection
Andy Lutomirski 4de0b6
  */
Andy Lutomirski 4de0b6
 static int read_byte(connection_t *src)
Andy Lutomirski 4de0b6
 {
Andy Lutomirski 4de0b6
diff --git a/env_universal_common.h b/env_universal_common.h
Andy Lutomirski 4de0b6
index 0a13a41..deddfb3 100644
Andy Lutomirski 4de0b6
--- a/env_universal_common.h
Andy Lutomirski 4de0b6
+++ b/env_universal_common.h
Andy Lutomirski 4de0b6
@@ -33,9 +33,9 @@
Andy Lutomirski 8e15cc
 
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 /**
Andy Lutomirski 4de0b6
-   The filename to use for univeral variables. The username is appended
Andy Lutomirski 4de0b6
+   The filename to use for univeral variables.
Andy Lutomirski 4de0b6
 */
Andy Lutomirski 4de0b6
-#define SOCK_FILENAME "fishd.socket."
Andy Lutomirski 4de0b6
+#define SOCK_FILENAME "fishd.socket"
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 /**
Andy Lutomirski 4de0b6
    The different types of commands that can be sent between client/server
Andy Lutomirski 4de0b6
@@ -134,6 +134,11 @@ void try_send_all(connection_t *c);
Andy Lutomirski 4de0b6
 message_t *create_message(fish_message_type_t type, const wchar_t *key, const wchar_t *val);
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 /**
Andy Lutomirski 4de0b6
+   Constructs the fish socket filename
Andy Lutomirski 4de0b6
+*/
Andy Lutomirski 4de0b6
+std::string env_universal_common_get_socket_filename(void);
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
+/**
Andy Lutomirski 4de0b6
    Init the library
Andy Lutomirski 4de0b6
 */
Andy Lutomirski 4de0b6
 void env_universal_common_init(void (*cb)(fish_message_type_t type, const wchar_t *key, const wchar_t *val));
Andy Lutomirski 4de0b6
diff --git a/fish_pager.cpp b/fish_pager.cpp
Andy Lutomirski 4de0b6
index 9cde933..27bc80e 100644
Andy Lutomirski 4de0b6
--- a/fish_pager.cpp
Andy Lutomirski 4de0b6
+++ b/fish_pager.cpp
Andy Lutomirski 4de0b6
@@ -1033,7 +1033,7 @@ static void init(int mangle_descriptors, int out)
Andy Lutomirski 4de0b6
     }
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
-    env_universal_init(0, 0, 0, 0);
Andy Lutomirski 4de0b6
+    env_universal_init("", 0, 0, 0);
Andy Lutomirski 4de0b6
     input_common_init(&interrupt_handler);
Andy Lutomirski 4de0b6
     output_set_writer(&pager_buffered_writer);
Andy Lutomirski 4de0b6
 
Andy Lutomirski 8e15cc
diff --git a/fishd.cpp b/fishd.cpp
Andy Lutomirski 4de0b6
index edb79c2..dd43647 100644
Andy Lutomirski 8e15cc
--- a/fishd.cpp
Andy Lutomirski 8e15cc
+++ b/fishd.cpp
Andy Lutomirski 4de0b6
@@ -159,6 +159,27 @@ static int quit=0;
Andy Lutomirski 4de0b6
 */
Andy Lutomirski 4de0b6
 static std::string get_socket_filename(void)
Andy Lutomirski 4de0b6
 {
Andy Lutomirski 4de0b6
+    const char *dir = common_get_runtime_path();
Andy Lutomirski 4de0b6
+
Andy Lutomirski 4de0b6
+    std::string name;
Andy Lutomirski 4de0b6
+    name.reserve(strlen(dir) + strlen(SOCK_FILENAME) + 1);
Andy Lutomirski 4de0b6
+    name.append(dir);
Andy Lutomirski 4de0b6
+    name.push_back('/');
Andy Lutomirski 4de0b6
+    name.append(SOCK_FILENAME);
Andy Lutomirski 4de0b6
+
Andy Lutomirski 4de0b6
+    if (name.size() >= UNIX_PATH_MAX)
Andy Lutomirski 4de0b6
+    {
Andy Lutomirski 4de0b6
+        debug(1, L"Filename too long: '%s'", name.c_str());
Andy Lutomirski 4de0b6
+        exit(EXIT_FAILURE);
Andy Lutomirski 4de0b6
+    }
Andy Lutomirski 4de0b6
+    return name;
Andy Lutomirski 4de0b6
+}
Andy Lutomirski 4de0b6
+
Andy Lutomirski 4de0b6
+/**
Andy Lutomirski 4de0b6
+    Constructs the legacy socket filename
Andy Lutomirski 4de0b6
+*/
Andy Lutomirski 4de0b6
+static std::string get_old_socket_filename(void)
Andy Lutomirski 4de0b6
+{
Andy Lutomirski 4de0b6
     const char *dir = getenv("FISHD_SOCKET_DIR");
Andy Lutomirski 4de0b6
     char *uname = getenv("USER");
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
@@ -174,10 +195,9 @@ static std::string get_socket_filename(void)
Andy Lutomirski 4de0b6
     }
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
     std::string name;
Andy Lutomirski 4de0b6
-    name.reserve(strlen(dir)+ strlen(uname)+ strlen(SOCK_FILENAME) + 1);
Andy Lutomirski 4de0b6
+    name.reserve(strlen(dir)+ strlen(uname)+ strlen("fishd.socket.") + 1);
Andy Lutomirski 4de0b6
     name.append(dir);
Andy Lutomirski 4de0b6
-    name.push_back('/');
Andy Lutomirski 4de0b6
-    name.append(SOCK_FILENAME);
Andy Lutomirski 4de0b6
+    name.append("/fishd.socket.");
Andy Lutomirski 4de0b6
     name.append(uname);
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
     if (name.size() >= UNIX_PATH_MAX)
Andy Lutomirski 4de0b6
@@ -541,6 +561,7 @@ repeat:
Andy Lutomirski 4de0b6
     int exitcode = EXIT_FAILURE;
Andy Lutomirski 4de0b6
     struct sockaddr_un local;
Andy Lutomirski 4de0b6
     const std::string sock_name = get_socket_filename();
Andy Lutomirski 4de0b6
+    const std::string old_sock_name = get_old_socket_filename();
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
     /*
Andy Lutomirski 4de0b6
        Start critical section protected by lock
Andy Lutomirski 4de0b6
@@ -598,6 +619,19 @@ repeat:
Andy Lutomirski 4de0b6
         doexit = 1;
Andy Lutomirski 4de0b6
     }
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
+    // Attempt to hardlink the old socket name so that old versions of fish keep working on upgrade
Andy Lutomirski 4de0b6
+    // Not critical if it fails
Andy Lutomirski 4de0b6
+    if (unlink(old_sock_name.c_str()) != 0 && errno != ENOENT)
Andy Lutomirski 4de0b6
+    {
Andy Lutomirski 4de0b6
+        debug(0, L"Could not create legacy socket path");
Andy Lutomirski 4de0b6
+        wperror(L"unlink");
Andy Lutomirski 4de0b6
+    }
Andy Lutomirski 4de0b6
+    else if (link(sock_name.c_str(), old_sock_name.c_str()) != 0)
Andy Lutomirski 4de0b6
+    {
Andy Lutomirski 4de0b6
+        debug(0, L"Could not create legacy socket path");
Andy Lutomirski 4de0b6
+        wperror(L"link");
Andy Lutomirski 4de0b6
+    }
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
 unlock:
Andy Lutomirski 4de0b6
     (void)unlink(lockfile.c_str());
Andy Lutomirski 4de0b6
     debug(4, L"Released lockfile: %s", lockfile.c_str());
Andy Lutomirski 4de0b6
@@ -873,6 +907,18 @@ static void init()
Andy Lutomirski 4de0b6
 }
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
 /**
Andy Lutomirski 4de0b6
+   Clean up behind ourselves
Andy Lutomirski 4de0b6
+*/
Andy Lutomirski 4de0b6
+static void cleanup()
Andy Lutomirski 4de0b6
+{
Andy Lutomirski 4de0b6
+    if (unlink(get_old_socket_filename().c_str()) != 0)
Andy Lutomirski 4de0b6
+    {
Andy Lutomirski 4de0b6
+        debug(0, L"Could not remove legacy socket path");
Andy Lutomirski 4de0b6
+        wperror(L"unlink");
Andy Lutomirski 4de0b6
+    }
Andy Lutomirski 4de0b6
+}
Andy Lutomirski 8e15cc
+
Andy Lutomirski 4de0b6
+/**
Andy Lutomirski 4de0b6
    Main function for fishd
Andy Lutomirski 4de0b6
 */
Andy Lutomirski 4de0b6
 int main(int argc, char ** argv)
Andy Lutomirski 4de0b6
@@ -973,6 +1019,7 @@ int main(int argc, char ** argv)
Andy Lutomirski 4de0b6
             if (quit)
Andy Lutomirski 4de0b6
             {
Andy Lutomirski 4de0b6
                 save();
Andy Lutomirski 4de0b6
+                cleanup();
Andy Lutomirski 4de0b6
                 exit(0);
Andy Lutomirski 4de0b6
             }
Andy Lutomirski 4de0b6
 
Andy Lutomirski 4de0b6
@@ -982,6 +1029,7 @@ int main(int argc, char ** argv)
Andy Lutomirski 4de0b6
             if (errno != EINTR)
Andy Lutomirski 4de0b6
             {
Andy Lutomirski 4de0b6
                 wperror(L"select");
Andy Lutomirski 4de0b6
+                cleanup();
Andy Lutomirski 4de0b6
                 exit(1);
Andy Lutomirski 4de0b6
             }
Andy Lutomirski 4de0b6
         }
Andy Lutomirski 4de0b6
@@ -994,6 +1042,7 @@ int main(int argc, char ** argv)
Andy Lutomirski 4de0b6
                                &t)) == -1)
Andy Lutomirski 4de0b6
             {
Andy Lutomirski 4de0b6
                 wperror(L"accept");
Andy Lutomirski 4de0b6
+                cleanup();
Andy Lutomirski 4de0b6
                 exit(1);
Andy Lutomirski 4de0b6
             }
Andy Lutomirski 4de0b6
             else
Andy Lutomirski 4de0b6
@@ -1070,6 +1119,7 @@ int main(int argc, char ** argv)
Andy Lutomirski 4de0b6
         {
Andy Lutomirski 4de0b6
             debug(0, L"No more clients. Quitting");
Andy Lutomirski 4de0b6
             save();
Andy Lutomirski 4de0b6
+            cleanup();
Andy Lutomirski 4de0b6
             break;
Andy Lutomirski 4de0b6
         }
Andy Lutomirski 8e15cc
 
Andy Lutomirski 8e15cc
-- 
Andy Lutomirski 4de0b6
1.9.3
Andy Lutomirski 8e15cc