X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=loginutils%2Fvlock.c;h=85f489c2286d1b5574e5a339139be1941c7fb391;hb=d7a805efafd83203e72c334089c3f88204231ac7;hp=d472c09251d788311f8ce89b23de43fd0beec7c0;hpb=d9867320b44dadfb707530eca6a88b5ffceca7ca;p=oweals%2Fbusybox.git diff --git a/loginutils/vlock.c b/loginutils/vlock.c index d472c0925..85f489c22 100644 --- a/loginutils/vlock.c +++ b/loginutils/vlock.c @@ -1,5 +1,4 @@ /* vi: set sw=4 ts=4: */ - /* * vlock implementation for busybox * @@ -16,88 +15,66 @@ /* Fixed by Erik Andersen to do passwords the tinylogin way... * It now works with md5, sha1, etc passwords. */ -#include "busybox.h" #include +#include "libbb.h" -static struct passwd *pw; -static struct vt_mode ovtm; -static struct termios oterm; -static int vfd; -static unsigned long o_lock_all; - -static void release_vt(int signo) -{ - if (!o_lock_all) - ioctl(vfd, VT_RELDISP, 1); - else - ioctl(vfd, VT_RELDISP, 0); -} - -static void acquire_vt(int signo) +static void release_vt(int signo UNUSED_PARAM) { - ioctl(vfd, VT_RELDISP, VT_ACKACQ); + /* If -a, param is 0, which means: + * "no, kernel, we don't allow console switch away from us!" */ + ioctl(STDIN_FILENO, VT_RELDISP, (unsigned long) !option_mask32); } -static void restore_terminal(void) +static void acquire_vt(int signo UNUSED_PARAM) { - ioctl(vfd, VT_SETMODE, &ovtm); - tcsetattr(STDIN_FILENO, TCSANOW, &oterm); + /* ACK to kernel that switch to console is successful */ + ioctl(STDIN_FILENO, VT_RELDISP, VT_ACKACQ); } -int vlock_main(int argc, char **argv) +int vlock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int vlock_main(int argc UNUSED_PARAM, char **argv) { - sigset_t sig; - struct sigaction sa; struct vt_mode vtm; struct termios term; - - if (argc > 2) { - bb_show_usage(); - } - - o_lock_all = bb_getopt_ulflags (argc, argv, "a"); - - if((pw = getpwuid(getuid())) == NULL) { - bb_error_msg_and_die("Unknown uid %d", getuid()); - } - - vfd = xopen(CURRENT_TTY, O_RDWR); - - if (ioctl(vfd, VT_GETMODE, &vtm) < 0) { - bb_perror_msg_and_die("VT_GETMODE"); - } - - /* mask a bunch of signals */ - sigprocmask(SIG_SETMASK, NULL, &sig); - sigdelset(&sig, SIGUSR1); - sigdelset(&sig, SIGUSR2); - sigaddset(&sig, SIGTSTP); - sigaddset(&sig, SIGTTIN); - sigaddset(&sig, SIGTTOU); - sigaddset(&sig, SIGHUP); - sigaddset(&sig, SIGCHLD); - sigaddset(&sig, SIGQUIT); - sigaddset(&sig, SIGINT); - - sigemptyset(&(sa.sa_mask)); - sa.sa_flags = SA_RESTART; - sa.sa_handler = release_vt; - sigaction(SIGUSR1, &sa, NULL); - sa.sa_handler = acquire_vt; - sigaction(SIGUSR2, &sa, NULL); - - /* need to handle some signals so that we don't get killed by them */ - sa.sa_handler = SIG_IGN; - sigaction(SIGHUP, &sa, NULL); - sigaction(SIGQUIT, &sa, NULL); - sigaction(SIGINT, &sa, NULL); - sigaction(SIGTSTP, &sa, NULL); - + struct termios oterm; + struct vt_mode ovtm; + struct passwd *pw; + + pw = xgetpwuid(getuid()); + opt_complementary = "=0"; /* no params! */ + getopt32(argv, "a"); + + /* Ignore some signals so that we don't get killed by them */ + bb_signals(0 + + (1 << SIGTSTP) + + (1 << SIGTTIN) + + (1 << SIGTTOU) + + (1 << SIGHUP ) + + (1 << SIGCHLD) /* paranoia :) */ + + (1 << SIGQUIT) + + (1 << SIGINT ) + , SIG_IGN); + + /* We will use SIGUSRx for console switch control: */ + /* 1: set handlers */ + signal_SA_RESTART_empty_mask(SIGUSR1, release_vt); + signal_SA_RESTART_empty_mask(SIGUSR2, acquire_vt); + /* 2: unmask them */ + sig_unblock(SIGUSR1); + sig_unblock(SIGUSR2); + + /* Revert stdin/out to our controlling tty + * (or die if we have none) */ + xmove_fd(xopen(CURRENT_TTY, O_RDWR), STDIN_FILENO); + xdup2(STDIN_FILENO, STDOUT_FILENO); + + xioctl(STDIN_FILENO, VT_GETMODE, &vtm); ovtm = vtm; + /* "console switches are controlled by us, not kernel!" */ vtm.mode = VT_PROCESS; vtm.relsig = SIGUSR1; vtm.acqsig = SIGUSR2; - ioctl(vfd, VT_SETMODE, &vtm); + ioctl(STDIN_FILENO, VT_SETMODE, &vtm); tcgetattr(STDIN_FILENO, &oterm); term = oterm; @@ -105,16 +82,20 @@ int vlock_main(int argc, char **argv) term.c_iflag |= IGNBRK; term.c_lflag &= ~ISIG; term.c_lflag &= ~(ECHO | ECHOCTL); - tcsetattr(STDIN_FILENO, TCSANOW, &term); + tcsetattr_stdin_TCSANOW(&term); do { - printf("Virtual Console%s locked by %s.\n", (o_lock_all) ? "s" : "", pw->pw_name); + printf("Virtual console%s locked by %s.\n", + option_mask32 /*o_lock_all*/ ? "s" : "", + pw->pw_name); if (correct_password(pw)) { break; } bb_do_delay(FAIL_DELAY); puts("Password incorrect"); } while (1); - restore_terminal(); - return 0; + + ioctl(STDIN_FILENO, VT_SETMODE, &ovtm); + tcsetattr_stdin_TCSANOW(&oterm); + fflush_stdout_and_exit(EXIT_SUCCESS); }