diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 6c0353d6..03254e9c 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -22,3 +22,4 @@ luna_app(rm.cpp rm) luna_app(stat.cpp stat) luna_app(uname.cpp uname) luna_app(base64.cpp base64) +luna_app(login.cpp login) diff --git a/apps/login.cpp b/apps/login.cpp new file mode 100644 index 00000000..9b8e14fd --- /dev/null +++ b/apps/login.cpp @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include + +Result luna_main(int argc, char** argv) +{ + StringView username; + + os::ArgumentParser parser; + parser.add_description("Begin a new session on the system."); + parser.add_system_program_info("login"_sv); + parser.add_positional_argument(username, "user", false); + parser.parse(argc, argv); + + if (geteuid() != 0) + { + os::eprintln("error: login must be run as root."); + return 1; + } + + putchar('\n'); + + String name; + + if (username.is_empty()) + { + auto input = os::File::standard_input(); + + os::print("Username: "); + + name = TRY(input->read_line()); + name.trim("\n"); + + if (name.is_empty()) return 0; + + username = name.view(); + } + + execl("/bin/su", "login", "-p", "--", username.chars(), nullptr); + + perror("su"); + return 1; +} diff --git a/apps/su.cpp b/apps/su.cpp index 2f544e6b..0f6d8486 100644 --- a/apps/su.cpp +++ b/apps/su.cpp @@ -54,10 +54,11 @@ char* getpass() Result luna_main(int argc, char** argv) { StringView name; + bool prompt_password; if (geteuid() != 0) { - fprintf(stderr, "su must be setuid root!\n"); + fprintf(stderr, "%s must be setuid root!\n", argv[0]); return 1; } @@ -65,23 +66,24 @@ Result luna_main(int argc, char** argv) parser.add_description("Switch to a different user (by default, root)."_sv); parser.add_system_program_info("su"_sv); parser.add_positional_argument(name, "name"_sv, "root"_sv); + parser.add_switch_argument(prompt_password, 'p', "prompt", "prompt for a password even if running as root"); parser.parse(argc, argv); struct passwd* entry = getpwnam(name.chars()); if (!entry) { - fprintf(stderr, "su: user %s not found!\n", name.chars()); + fprintf(stderr, "%s: user %s not found!\n", argv[0], name.chars()); return 1; } - if (getuid() != geteuid() && *entry->pw_passwd) + if ((prompt_password || getuid() != geteuid()) && *entry->pw_passwd) { char* pass = getpass(); if (!pass) return 1; if (strcmp(pass, entry->pw_passwd)) { - fprintf(stderr, "Wrong password!\n"); + fprintf(stderr, "%s: wrong password!\n", argv[0]); return 1; } diff --git a/initrd/etc/init/99-shell b/initrd/etc/init/99-login similarity index 57% rename from initrd/etc/init/99-shell rename to initrd/etc/init/99-login index 2f6fb30e..631fd293 100644 --- a/initrd/etc/init/99-shell +++ b/initrd/etc/init/99-login @@ -1,4 +1,4 @@ -Name=shell -Command=/bin/sh +Name=login +Command=/bin/login Restart=true Environment=PATH=/bin:/sbin