#include "command.h" #include "lslib.h" #include #include #include static struct { bool clear_env; bool update_env; char* shell; char* user; } flags; static bool restricted_shell(const char *shell) { char *line; bool result = true; while ((line = getusershell()) != NULL) { if (strcmp(line, shell) == 0) { result = false; break; } } endusershell(); return result; } static void help (void) { printf("Usage: su [-lmp] [-s SH] [-] [USER [FILE ARGS]] \n\n"); printf("Run shell under USER (by default, root)\n\n"); printf("\t-,-l\tClear environment, go to home dir, run shell as login shell\n"); printf("\t-p,-m\tDo not set new $HOME, $SHELL, $USER, $LOGNAME\n"); printf("\t-s SH Shell\tto use instead of user's default\n"); } static int short_arg (char c, char* next) { switch (c) { case 'l': flags.clear_env = true; break; case 'p': case 'm': flags.update_env = false; break; case 's': check_arg(next); flags.shell = next; return ARG_USED; default: return ARG_INVALID; } return ARG_UNUSED; } COMMAND (su_main) { int start, res; uid_t cur_uid; struct passwd* pw; flags.clear_env = false; flags.update_env = true; flags.shell = NULL; flags.user = "root"; start = parse_args(argc, argv, help, short_arg, NULL); if (start < argc && streql(argv[start], "-")) { flags.clear_env = true; start++; } if (start < argc) flags.user = argv[start++]; pw = xgetpwnam(flags.user); cur_uid = getuid(); if (cur_uid != 0) res = prompt_password(pw, "Password: "); else res = PASSWORD_VALID; if (res != PASSWORD_VALID) error("invalid password"); if (flags.shell && cur_uid != 0 && pw->pw_shell && restricted_shell(pw->pw_shell)) { error_s("using restricted shell"); flags.shell = NULL; } if (!flags.shell) flags.shell = pw->pw_shell; change_identity(pw); setup_environment(flags.shell, flags.update_env, flags.clear_env, pw); exec_shell(flags.shell, flags.clear_env, (const char**) &argv[start]); return EXIT_FAILURE; /* */ }