104 lines
2.3 KiB
C
104 lines
2.3 KiB
C
#include "command.h"
|
|
#include "lslib.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
static struct {
|
|
bool clear_env;
|
|
bool update_env;
|
|
char* shell;
|
|
char* user;
|
|
} flags;
|
|
|
|
static bool restricted_shell(const char *shell) {
|
|
char *line;
|
|
int 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) {
|
|
|
|
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; /* */
|
|
}
|