Serenity Operating System
1/*
2 * Copyright (c) 2021, the SerenityOS developers.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/Vector.h>
8#include <LibCore/Account.h>
9#include <LibCore/ArgsParser.h>
10#include <LibCore/System.h>
11#include <LibMain/Main.h>
12#include <grp.h>
13#include <unistd.h>
14
15static void print_account_gids(Core::Account const& account)
16{
17 auto* gr = getgrgid(account.gid());
18 if (!gr) {
19 outln();
20 return;
21 }
22
23 out("{}", gr->gr_name);
24 for (auto& gid : account.extra_gids()) {
25 gr = getgrgid(gid);
26 out(" {}", gr->gr_name);
27 }
28 outln();
29}
30
31ErrorOr<int> serenity_main(Main::Arguments arguments)
32{
33 TRY(Core::System::unveil("/etc/passwd", "r"));
34 TRY(Core::System::unveil("/etc/group", "r"));
35 TRY(Core::System::unveil(nullptr, nullptr));
36 TRY(Core::System::pledge("stdio rpath"));
37
38 Vector<DeprecatedString> usernames;
39
40 Core::ArgsParser args_parser;
41 args_parser.set_general_help("Print group memberships for each username or, if no username is specified, for the current process.");
42 args_parser.add_positional_argument(usernames, "Usernames to list group memberships for", "usernames", Core::ArgsParser::Required::No);
43 args_parser.parse(arguments);
44
45 if (usernames.is_empty()) {
46 auto account = TRY(Core::Account::from_uid(geteuid(), Core::Account::Read::PasswdOnly));
47 print_account_gids(account);
48 }
49
50 for (auto const& username : usernames) {
51 auto result = Core::Account::from_name(username, Core::Account::Read::PasswdOnly);
52 if (result.is_error()) {
53 warnln("{} '{}'", result.error(), username);
54 continue;
55 }
56 out("{} : ", username);
57 print_account_gids(result.value());
58 }
59 return 0;
60}