Skip to content

Commit f47f8a2

Browse files
committed
who: Add who command
1 parent dd7666e commit f47f8a2

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

Userland/Utilities/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ set(CMD_SOURCES_CPP
212212
watchfs.cpp
213213
wc.cpp
214214
which.cpp
215+
who.cpp
215216
whoami.cpp
216217
wsctl.cpp
217218
xargs.cpp

Userland/Utilities/who.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright (c) 2024, Edward <[email protected]>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
#include <AK/Format.h>
8+
#include <AK/JsonArray.h>
9+
#include <AK/JsonObject.h>
10+
#include <AK/JsonParser.h>
11+
#include <AK/JsonValue.h>
12+
#include <LibCore/File.h>
13+
#include <LibCore/System.h>
14+
#include <LibMain/Main.h>
15+
#include <pwd.h>
16+
#include <time.h>
17+
18+
ErrorOr<int> serenity_main(Main::Arguments)
19+
{
20+
// TRY(Core::System::pledge("stdio rpath"));
21+
// TRY(Core::System::unveil("/var/run/utmp", "r"));
22+
// TRY(Core::System::unveil(nullptr, nullptr));
23+
24+
auto file = TRY(Core::File::open("/var/run/utmp"sv, Core::File::OpenMode::Read));
25+
auto contents = TRY(file->read_until_eof());
26+
auto json = TRY(JsonValue::from_string(contents));
27+
28+
// outln("{}", StringView(contents));
29+
30+
json.as_object().for_each_member([&](auto& key, auto& value) {
31+
// outln("key: {}", key);
32+
33+
auto const& obj = value.as_object();
34+
35+
auto uid = obj.get_i32("uid"sv).value_or(0);
36+
// outln("uid: {}", uid);
37+
38+
auto* passwd = getpwuid(uid);
39+
auto user_name = passwd->pw_name;
40+
// outln("user_name: {}", passwd->pw_name);
41+
42+
auto login_at = obj.get_i32("login_at"sv).value_or(0);
43+
// outln("login_at: {}", login_at);
44+
45+
auto time = static_cast<time_t>(login_at);
46+
auto* tm = localtime(&time);
47+
char timebuf[32];
48+
strftime(timebuf, sizeof(timebuf), "%b %d %H:%M", tm);
49+
// outln("login_at (formatted): {}", timebuf);
50+
51+
outln("{}\t{}\t{}", user_name, key, timebuf);
52+
});
53+
54+
// outln("{}", json.as_string());
55+
56+
// auto entries = json.as_array();
57+
// for (auto const& entry : entries.values()) {
58+
// if (!entry.is_object())
59+
// continue;
60+
61+
// auto const& obj = entry.as_object();
62+
// auto username = obj.get_byte_string("username"sv).value_or(""sv);
63+
// auto tty = obj.get_byte_string("tty"sv).value_or(""sv);
64+
// auto hostname = obj.get_byte_string("hostname"sv).value_or(""sv);
65+
// auto timestamp = obj.get_integer<time_t>("timestamp"sv).value_or(0);
66+
67+
// if (username.is_empty() || tty.is_empty())
68+
// continue;
69+
70+
// char timebuf[32];
71+
// struct tm* tm = localtime(&timestamp);
72+
// strftime(timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M", tm);
73+
74+
// outln("{:<8} {:<12} {:<15} {}", username, tty, hostname, timebuf);
75+
// }
76+
77+
return 0;
78+
}

0 commit comments

Comments
 (0)