1/* vi: set sw=4 ts=4: */ 2 3/* 4 * vlock implementation for busybox 5 * 6 * Copyright (C) 2000 by spoon <spoon@ix.netcom.com> 7 * Written by spoon <spon@ix.netcom.com> 8 * 9 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 10 */ 11 12/* Shoutz to Michael K. Johnson <johnsonm@redhat.com>, author of the 13 * original vlock. I snagged a bunch of his code to write this 14 * minimalistic vlock. 15 */ 16/* Fixed by Erik Andersen to do passwords the tinylogin way... 17 * It now works with md5, sha1, etc passwords. */ 18 19#include "libbb.h" 20#include <sys/vt.h> 21 22static struct passwd *pw; 23static struct vt_mode ovtm; 24static struct termios oterm; 25static int vfd; 26static unsigned long o_lock_all; 27 28static void release_vt(int signo) 29{ 30 ioctl(vfd, VT_RELDISP, !o_lock_all); 31} 32 33static void acquire_vt(int signo) 34{ 35 ioctl(vfd, VT_RELDISP, VT_ACKACQ); 36} 37 38static void restore_terminal(void) 39{ 40 ioctl(vfd, VT_SETMODE, &ovtm); 41 tcsetattr(STDIN_FILENO, TCSANOW, &oterm); 42} 43 44int vlock_main(int argc, char **argv); 45int vlock_main(int argc, char **argv) 46{ 47 sigset_t sig; 48 struct sigaction sa; 49 struct vt_mode vtm; 50 struct termios term; 51 uid_t uid = getuid(); 52 53 pw = getpwuid(uid); 54 if (pw == NULL) 55 bb_error_msg_and_die("unknown uid %d", uid); 56 57 if (argc > 2) { 58 bb_show_usage(); 59 } 60 61 o_lock_all = getopt32(argv, "a"); 62 63 vfd = xopen(CURRENT_TTY, O_RDWR); 64 65 xioctl(vfd, VT_GETMODE, &vtm); 66 67 /* mask a bunch of signals */ 68 sigprocmask(SIG_SETMASK, NULL, &sig); 69 sigdelset(&sig, SIGUSR1); 70 sigdelset(&sig, SIGUSR2); 71 sigaddset(&sig, SIGTSTP); 72 sigaddset(&sig, SIGTTIN); 73 sigaddset(&sig, SIGTTOU); 74 sigaddset(&sig, SIGHUP); 75 sigaddset(&sig, SIGCHLD); 76 sigaddset(&sig, SIGQUIT); 77 sigaddset(&sig, SIGINT); 78 79 sigemptyset(&(sa.sa_mask)); 80 sa.sa_flags = SA_RESTART; 81 sa.sa_handler = release_vt; 82 sigaction(SIGUSR1, &sa, NULL); 83 sa.sa_handler = acquire_vt; 84 sigaction(SIGUSR2, &sa, NULL); 85 86 /* need to handle some signals so that we don't get killed by them */ 87 sa.sa_handler = SIG_IGN; 88 sigaction(SIGHUP, &sa, NULL); 89 sigaction(SIGQUIT, &sa, NULL); 90 sigaction(SIGINT, &sa, NULL); 91 sigaction(SIGTSTP, &sa, NULL); 92 93 ovtm = vtm; 94 vtm.mode = VT_PROCESS; 95 vtm.relsig = SIGUSR1; 96 vtm.acqsig = SIGUSR2; 97 ioctl(vfd, VT_SETMODE, &vtm); 98 99 tcgetattr(STDIN_FILENO, &oterm); 100 term = oterm; 101 term.c_iflag &= ~BRKINT; 102 term.c_iflag |= IGNBRK; 103 term.c_lflag &= ~ISIG; 104 term.c_lflag &= ~(ECHO | ECHOCTL); 105 tcsetattr(STDIN_FILENO, TCSANOW, &term); 106 107 do { 108 printf("Virtual Console%s locked by %s.\n", (o_lock_all) ? "s" : "", pw->pw_name); 109 if (correct_password(pw)) { 110 break; 111 } 112 bb_do_delay(FAIL_DELAY); 113 puts("Password incorrect"); 114 } while (1); 115 restore_terminal(); 116 fflush_stdout_and_exit(0); 117} 118