/* vi: set sw=4 ts=4: */ /* * vlock implementation for busybox * * Copyright (C) 2000 by spoon <spoon@ix.netcom.com> * Written by spoon <spon@ix.netcom.com> * * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ /* Shoutz to Michael K. Johnson <johnsonm@redhat.com>, author of the * original vlock. I snagged a bunch of his code to write this * minimalistic vlock. */ /* Fixed by Erik Andersen to do passwords the tinylogin way... * It now works with md5, sha1, etc passwords. */ #include <stdio.h> #include <stdlib.h> #include <sys/vt.h> #include <signal.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <sys/ioctl.h> #include <termios.h> #include "busybox.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) { ioctl(vfd, VT_RELDISP, VT_ACKACQ); } static void restore_terminal(void) { ioctl(vfd, VT_SETMODE, &ovtm); tcsetattr(STDIN_FILENO, TCSANOW, &oterm); } int vlock_main(int argc, 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 = bb_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); ovtm = vtm; vtm.mode = VT_PROCESS; vtm.relsig = SIGUSR1; vtm.acqsig = SIGUSR2; ioctl(vfd, VT_SETMODE, &vtm); tcgetattr(STDIN_FILENO, &oterm); term = oterm; term.c_iflag &= ~BRKINT; term.c_iflag |= IGNBRK; term.c_lflag &= ~ISIG; term.c_lflag &= ~(ECHO | ECHOCTL); tcsetattr(STDIN_FILENO, TCSANOW, &term); do { printf("Virtual Console%s locked.\n%s's ", (o_lock_all) ? "s" : "", pw->pw_name); fflush(stdout); if (correct_password (pw)) { break; } bb_do_delay(FAIL_DELAY); puts("Password incorrect."); } while (1); restore_terminal(); return 0; }