diff --git a/src/remote.cc b/src/remote.cc index 83fc8adc..7f6cb817 100644 --- a/src/remote.cc +++ b/src/remote.cc @@ -537,18 +537,35 @@ String get_user_name() return getenv("USER"); } +void make_session_directory() +{ + StringView xdg_runtime_dir = getenv("XDG_RUNTIME_DIR"); + if (xdg_runtime_dir.empty()) + { + // set sticky bit on the shared kakoune directory + make_directory(format("{}/kakoune", tmpdir()), 01777); + make_directory(format("{}/kakoune/{}", tmpdir(), get_user_name()), 0711); + } + else + make_directory(format("{}/kakoune", xdg_runtime_dir), 0711); +} + +String session_path(StringView session) +{ + if (contains(session, '/')) + throw runtime_error{"session names cannot have slashes"}; + StringView xdg_runtime_dir = getenv("XDG_RUNTIME_DIR"); + if (xdg_runtime_dir.empty()) + return format("{}/kakoune/{}/{}", tmpdir(), get_user_name(), session); + else + return format("{}/kakoune/{}", xdg_runtime_dir, session); +} + static sockaddr_un session_addr(StringView session) { sockaddr_un addr; addr.sun_family = AF_UNIX; - auto slash_count = std::count(session.begin(), session.end(), '/'); - if (slash_count > 1) - throw runtime_error{"session names are either / or "}; - else if (slash_count == 1) - format_to(addr.sun_path, "{}/kakoune/{}", tmpdir(), session); - else - format_to(addr.sun_path, "{}/kakoune/{}/{}", tmpdir(), - get_user_name(), session); + strcpy(addr.sun_path, session_path(session).c_str()); return addr; } @@ -784,9 +801,7 @@ Server::Server(String session_name) fcntl(listen_sock, F_SETFD, FD_CLOEXEC); sockaddr_un addr = session_addr(m_session); - // set sticky bit on the shared kakoune directory - make_directory(format("{}/kakoune", tmpdir()), 01777); - make_directory(split_path(addr.sun_path).first, 0711); + make_session_directory(); // Do not give any access to the socket to other users by default auto old_mask = umask(0077); @@ -819,10 +834,8 @@ bool Server::rename_session(StringView name) if (not all_of(name, is_identifier)) throw runtime_error{format("invalid session name: '{}'", name)}; - String old_socket_file = format("{}/kakoune/{}/{}", tmpdir(), - get_user_name(), m_session); - String new_socket_file = format("{}/kakoune/{}/{}", tmpdir(), - get_user_name(), name); + String old_socket_file = session_path(m_session); + String new_socket_file = session_path(name); if (file_exists(new_socket_file)) return false; @@ -838,8 +851,7 @@ void Server::close_session(bool do_unlink) { if (do_unlink) { - String socket_file = format("{}/kakoune/{}/{}", tmpdir(), - get_user_name(), m_session); + String socket_file = session_path(m_session); unlink(socket_file.c_str()); } m_listener->close_fd(); diff --git a/src/remote.hh b/src/remote.hh index fa04b006..4a3b0efc 100644 --- a/src/remote.hh +++ b/src/remote.hh @@ -45,6 +45,7 @@ private: void send_command(StringView session, StringView command); String get_user_name(); +String session_path(StringView session); struct Server : public Singleton {