1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 23:47:45 +00:00

su: Add the --login option

This option, often used with only a lonely dash, allows to "simulate a
login". For now, it just changes the current directory to the home of
the new user.
This commit is contained in:
Lucas CHOLLET 2022-06-10 21:09:38 +02:00 committed by Sam Atkins
parent 507cb411c2
commit 6900c4fe29
2 changed files with 23 additions and 7 deletions

View file

@ -5,13 +5,11 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/ScopeGuard.h>
#include <LibCore/Account.h>
#include <LibCore/ArgsParser.h>
#include <LibCore/GetPassword.h>
#include <LibCore/System.h>
#include <LibMain/Main.h>
#include <stdio.h>
#include <unistd.h>
ErrorOr<int> serenity_main(Main::Arguments arguments)
@ -21,18 +19,29 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
if (!TRY(Core::System::isatty(STDIN_FILENO)))
return Error::from_string_literal("Standard input is not a terminal");
StringView user;
StringView first_positional;
StringView second_positional;
bool simulate_login = false;
Core::ArgsParser args_parser;
args_parser.add_positional_argument(user, "User to switch to (defaults to user with UID 0)", "user", Core::ArgsParser::Required::No);
args_parser.add_positional_argument(first_positional, "See --login", "-", Core::ArgsParser::Required::No);
args_parser.add_positional_argument(second_positional, "User to switch to (defaults to user with UID 0)", "user", Core::ArgsParser::Required::No);
args_parser.add_option(simulate_login, "Simulate login", "login", 'l');
args_parser.parse(arguments);
StringView user = first_positional;
if (first_positional == '-') {
simulate_login = true;
user = second_positional;
}
if (geteuid() != 0)
return Error::from_string_literal("Not running as root :(");
auto account = TRY(user.is_empty() ? Core::Account::from_uid(0) : Core::Account::from_name(user));
TRY(Core::System::pledge("stdio tty exec id"));
TRY(Core::System::pledge("stdio rpath tty exec id"));
if (getuid() != 0 && account.has_password()) {
auto password = TRY(Core::get_password());
@ -40,13 +49,16 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
return Error::from_string_literal("Incorrect or disabled password.");
}
TRY(Core::System::pledge("stdio exec id"));
TRY(Core::System::pledge("stdio rpath exec id"));
if (!account.login()) {
perror("Core::Account::login");
return 1;
}
if (simulate_login)
TRY(Core::System::chdir(account.home_directory()));
TRY(Core::System::pledge("stdio exec"));
TRY(Core::System::setenv("HOME"sv, account.home_directory(), true));