From c73e64882cf9e72e95e0a7836998ddd375703946 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 6 Jun 2016 19:28:56 +0100 Subject: [PATCH] Check session valididty on kak -l and support kak -clear for clearing the dead ones Fixes #689 --- README.asciidoc | 8 +++++++- src/main.cc | 23 +++++++++++++++++++---- src/remote.cc | 8 ++++++++ src/remote.hh | 2 ++ 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/README.asciidoc b/README.asciidoc index 570a6ffb4..f3c16e6a7 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -224,7 +224,13 @@ Just running *kak* launch a new kak session with a client on local terminal. acting as a remote control. * `-f `: Work as a filter, read every file given on the command line and stdin if piped in, and apply given keys on each. - * `-l`: list existing sessions + * `-ui `: use given user interface, `` can be + - `ncurses`: default terminal user interface + - `dummy`: empty user interface not displaying anything + - `json`: json-rpc based user interface that writes json on stdout and + read keystrokes as json on stdin. + * `-l`: list existing sessions, and check the dead ones + * `-clear`: clear dead sessions socket files At startup, if `-n` is not specified, Kakoune will try to source the file `../share/kak/kakrc` relative to the kak binary. This kak file will then try diff --git a/src/main.cc b/src/main.cc index 4db4f8838..03da5bba8 100644 --- a/src/main.cc +++ b/src/main.cc @@ -731,7 +731,8 @@ int main(int argc, char* argv[]) { "f", { true, "act as a filter, executing given keys on given files" } }, { "q", { false, "in filter mode, be quiet about errors applying keys" } }, { "ui", { true, "set the type of user interface to use (ncurses, dummy, or json)" } }, - { "l", { false, "list existing sessions" } } } + { "l", { false, "list existing sessions" } }, + { "clear", { false, "clear dead sessions" } } } }; try { @@ -741,12 +742,26 @@ int main(int argc, char* argv[]) ParametersParser parser(params, param_desc); - if (parser.get_switch("l")) + const bool list_sessions = (bool)parser.get_switch("l"); + const bool clear_sessions = (bool)parser.get_switch("clear"); + if (list_sessions or clear_sessions) { - for (auto& file : list_files(format("/tmp/kakoune/{}/", getpwuid(geteuid())->pw_name))) - write_stdout(format("{}\n", file)); + StringView username = getpwuid(geteuid())->pw_name; + for (auto& session : list_files(format("/tmp/kakoune/{}/", username))) + { + const bool valid = check_session(session); + if (list_sessions) + write_stdout(format("{}{}\n", session, valid ? "" : " (dead)")); + if (not valid and clear_sessions) + { + char socket_file[128]; + format_to(socket_file, "/tmp/kakoune/{}/{}", username, session); + unlink(socket_file); + } + } return 0; } + if (auto session = parser.get_switch("p")) { for (auto opt : { "c", "n", "s", "d", "e" }) diff --git a/src/remote.cc b/src/remote.cc index d5a747cc0..1c5a21350 100644 --- a/src/remote.cc +++ b/src/remote.cc @@ -436,6 +436,14 @@ static int connect_to(StringView session) return sock; } +bool check_session(StringView session) +{ + int sock = socket(AF_UNIX, SOCK_STREAM, 0); + auto close_sock = on_scope_end([sock]{ close(sock); }); + sockaddr_un addr = session_addr(session); + return connect(sock, (sockaddr*)&addr, sizeof(addr.sun_path)) != -1; +} + RemoteClient::RemoteClient(StringView session, std::unique_ptr&& ui, const EnvVarMap& env_vars, StringView init_command) : m_ui(std::move(ui)) diff --git a/src/remote.hh b/src/remote.hh index 1164d2bed..f127e1807 100644 --- a/src/remote.hh +++ b/src/remote.hh @@ -59,6 +59,8 @@ private: Vector> m_accepters; }; +bool check_session(StringView session); + } #endif // remote_hh_INCLUDED