use user's shell instead of hardwired "/bin/sh" (android needs this)
[platform/upstream/busybox.git] / loginutils / vlock.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * vlock implementation for busybox
4  *
5  * Copyright (C) 2000 by spoon <spoon@ix.netcom.com>
6  * Written by spoon <spon@ix.netcom.com>
7  *
8  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9  */
10
11 /* Shoutz to Michael K. Johnson <johnsonm@redhat.com>, author of the
12  * original vlock.  I snagged a bunch of his code to write this
13  * minimalistic vlock.
14  */
15 /* Fixed by Erik Andersen to do passwords the tinylogin way...
16  * It now works with md5, sha1, etc passwords. */
17
18 #include "libbb.h"
19
20 #ifdef __linux__
21 #include <sys/vt.h>
22
23 static void release_vt(int signo UNUSED_PARAM)
24 {
25         /* If -a, param is 0, which means:
26          * "no, kernel, we don't allow console switch away from us!" */
27         ioctl(STDIN_FILENO, VT_RELDISP, (unsigned long) !option_mask32);
28 }
29
30 static void acquire_vt(int signo UNUSED_PARAM)
31 {
32         /* ACK to kernel that switch to console is successful */
33         ioctl(STDIN_FILENO, VT_RELDISP, VT_ACKACQ);
34 }
35 #endif
36
37 int vlock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
38 int vlock_main(int argc UNUSED_PARAM, char **argv)
39 {
40 #ifdef __linux__
41         struct vt_mode vtm;
42         struct vt_mode ovtm;
43 #endif
44         struct termios term;
45         struct termios oterm;
46         struct passwd *pw;
47
48         pw = xgetpwuid(getuid());
49         opt_complementary = "=0"; /* no params! */
50         getopt32(argv, "a");
51
52         /* Ignore some signals so that we don't get killed by them */
53         bb_signals(0
54                 + (1 << SIGTSTP)
55                 + (1 << SIGTTIN)
56                 + (1 << SIGTTOU)
57                 + (1 << SIGHUP )
58                 + (1 << SIGCHLD) /* paranoia :) */
59                 + (1 << SIGQUIT)
60                 + (1 << SIGINT )
61                 , SIG_IGN);
62
63 #ifdef __linux__
64         /* We will use SIGUSRx for console switch control: */
65         /* 1: set handlers */
66         signal_SA_RESTART_empty_mask(SIGUSR1, release_vt);
67         signal_SA_RESTART_empty_mask(SIGUSR2, acquire_vt);
68         /* 2: unmask them */
69         sig_unblock(SIGUSR1);
70         sig_unblock(SIGUSR2);
71 #endif
72
73         /* Revert stdin/out to our controlling tty
74          * (or die if we have none) */
75         xmove_fd(xopen(CURRENT_TTY, O_RDWR), STDIN_FILENO);
76         xdup2(STDIN_FILENO, STDOUT_FILENO);
77
78 #ifdef __linux__
79         xioctl(STDIN_FILENO, VT_GETMODE, &vtm);
80         ovtm = vtm;
81         /* "console switches are controlled by us, not kernel!" */
82         vtm.mode = VT_PROCESS;
83         vtm.relsig = SIGUSR1;
84         vtm.acqsig = SIGUSR2;
85         ioctl(STDIN_FILENO, VT_SETMODE, &vtm);
86 #endif
87
88         tcgetattr(STDIN_FILENO, &oterm);
89         term = oterm;
90         term.c_iflag &= ~BRKINT;
91         term.c_iflag |= IGNBRK;
92         term.c_lflag &= ~ISIG;
93         term.c_lflag &= ~(ECHO | ECHOCTL);
94         tcsetattr_stdin_TCSANOW(&term);
95
96         while (1) {
97                 printf("Virtual console%s locked by %s.\n",
98                                 /* "s" if -a, else "": */ "s" + !option_mask32,
99                                 pw->pw_name
100                 );
101                 if (correct_password(pw)) {
102                         break;
103                 }
104                 bb_do_delay(FAIL_DELAY);
105                 puts("Password incorrect");
106         }
107
108 #ifdef __linux__
109         ioctl(STDIN_FILENO, VT_SETMODE, &ovtm);
110 #endif
111         tcsetattr_stdin_TCSANOW(&oterm);
112         fflush_stdout_and_exit(EXIT_SUCCESS);
113 }