#include #include #include #include #include #include #include static struct termios orig; void restore_terminal() { ioctl(fileno(stdin), TCSETS, &orig); } char* getpass() { fputs("Password: ", stdout); if (ioctl(fileno(stdin), TCGETS, &orig) < 0) { perror("ioctl(TCGETS)"); return nullptr; } atexit(restore_terminal); struct termios tc = orig; tc.c_lflag &= ~ECHO; if (ioctl(fileno(stdin), TCSETS, &tc) < 0) { perror("ioctl(TCSETS)"); return nullptr; } static char buf[1024]; char* rc = fgets(buf, sizeof(buf), stdin); restore_terminal(); putchar('\n'); if (!rc) { perror("fgets"); return nullptr; } char* newline = strrchr(rc, '\n'); if (newline) *newline = 0; return buf; } Result luna_main(int argc, char** argv) { StringView name; if (geteuid() != 0) { fprintf(stderr, "su must be setuid root!\n"); return 1; } os::ArgumentParser parser; parser.add_description("Switch to a different user (by default, root)."_sv); parser.add_positional_argument(name, "name"_sv, "root"_sv); parser.parse(argc, argv); struct passwd* entry = getpwnam(name.chars()); if (!entry) { fprintf(stderr, "su: user %s not found!\n", name.chars()); return 1; } if (getuid() != geteuid() && *entry->pw_passwd) { char* pass = getpass(); if (!pass) return 1; if (strcmp(pass, entry->pw_passwd)) { fprintf(stderr, "Wrong password!\n"); return 1; } memset(pass, 0, strlen(pass)); } setgid(entry->pw_gid); setuid(entry->pw_uid); chdir(entry->pw_dir); execl(entry->pw_shell, entry->pw_shell, NULL); return 1; }