summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2017-12-04 14:27:54 +0800
committerMaxime Coste <mawww@kakoune.org>2017-12-04 15:19:57 +0800
commit274367116a57c5788cc4b30861dcd94f54fba60e (patch)
tree0a0f611802cfc3ea50f2590640256f85467742c1 /src
parent7d32b3fc3689219d47fc236eefa4749f2e7c3c61 (diff)
Replace uses of getpwuid which is incompatible with static linking
Introduce a get_user_name function which parses '/etc/passwd' to find the username associated with a user id.
Diffstat (limited to 'src')
-rw-r--r--src/main.cc2
-rw-r--r--src/ranges.hh17
-rw-r--r--src/remote.cc25
-rw-r--r--src/remote.hh1
4 files changed, 40 insertions, 5 deletions
diff --git a/src/main.cc b/src/main.cc
index 4671511a..a112edce 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -891,7 +891,7 @@ int main(int argc, char* argv[])
const bool clear_sessions = (bool)parser.get_switch("clear");
if (list_sessions or clear_sessions)
{
- const StringView username = getpwuid(geteuid())->pw_name;
+ const String username = get_user_name(geteuid());
const StringView tmp_dir = tmpdir();
for (auto& session : list_files(format("{}/kakoune/{}/", tmp_dir,
username)))
diff --git a/src/ranges.hh b/src/ranges.hh
index fa23f180..599396dc 100644
--- a/src/ranges.hh
+++ b/src/ranges.hh
@@ -6,6 +6,8 @@
#include <iterator>
#include <numeric>
+#include "constexpr_utils.hh"
+
namespace Kakoune
{
@@ -337,6 +339,21 @@ auto gather()
});
}
+template<typename ExceptionType, size_t... Indexes>
+auto elements()
+{
+ return make_view_factory([] (auto&& range) {
+ using std::begin; using std::end;
+ auto elem = [it = begin(range), end = end(range), i = 0u](size_t index) mutable {
+ for (; i < index; ++i, ++it)
+ if (it == end) throw ExceptionType{i};
+ return *it;
+ };
+ // Note that initializer lists elements are guaranteed to be sequenced
+ return Array<std::decay_t<decltype(*begin(range))>, sizeof...(Indexes)>{{elem(Indexes)...}};
+ });
+}
+
}
#endif // ranges_hh_INCLUDED
diff --git a/src/remote.cc b/src/remote.cc
index ebd92f72..8cfbdc5b 100644
--- a/src/remote.cc
+++ b/src/remote.cc
@@ -528,6 +528,23 @@ void RemoteUI::exit(int status)
m_socket_watcher.events() |= FdEvents::Write;
}
+String get_user_name(int uid)
+{
+ struct invalid_index : runtime_error
+ {
+ invalid_index(size_t i) : runtime_error{format("invalid index '{}'", i)} {}
+ };
+
+ MappedFile passwd{"/etc/passwd"};
+ for (auto entry : (StringView)passwd | split<StringView>('\n'))
+ {
+ auto name_and_id = entry | split<StringView>(':') | elements<invalid_index, 0, 2>();
+ if (str_to_int(name_and_id[1]) == uid)
+ return name_and_id[0].str();
+ }
+ throw runtime_error(format("Cannot find user name for uid '{}'", uid));
+}
+
static sockaddr_un session_addr(StringView session)
{
sockaddr_un addr;
@@ -539,7 +556,7 @@ static sockaddr_un session_addr(StringView session)
format_to(addr.sun_path, "{}/kakoune/{}", tmpdir(), session);
else
format_to(addr.sun_path, "{}/kakoune/{}/{}", tmpdir(),
- getpwuid(geteuid())->pw_name, session);
+ get_user_name(geteuid()), session);
return addr;
}
@@ -813,9 +830,9 @@ bool Server::rename_session(StringView name)
throw runtime_error{"Cannot create sessions with '/' in their name"};
String old_socket_file = format("{}/kakoune/{}/{}", tmpdir(),
- getpwuid(geteuid())->pw_name, m_session);
+ get_user_name(geteuid()), m_session);
String new_socket_file = format("{}/kakoune/{}/{}", tmpdir(),
- getpwuid(geteuid())->pw_name, name);
+ get_user_name(geteuid()), name);
if (rename(old_socket_file.c_str(), new_socket_file.c_str()) != 0)
return false;
@@ -829,7 +846,7 @@ void Server::close_session(bool do_unlink)
if (do_unlink)
{
String socket_file = format("{}/kakoune/{}/{}", tmpdir(),
- getpwuid(geteuid())->pw_name, m_session);
+ get_user_name(geteuid()), m_session);
unlink(socket_file.c_str());
}
m_listener->close_fd();
diff --git a/src/remote.hh b/src/remote.hh
index d723713f..ce84cb42 100644
--- a/src/remote.hh
+++ b/src/remote.hh
@@ -43,6 +43,7 @@ private:
};
void send_command(StringView session, StringView command);
+String get_user_name(int uid);
struct Server : public Singleton<Server>
{