Move sed over to the generic llist_t for append. Saves about 90 bytes.
[oweals/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  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  */
23
24 /* Shoutz to Michael K. Johnson <johnsonm@redhat.com>, author of the
25  * original vlock.  I snagged a bunch of his code to write this
26  * minimalistic vlock.
27  */
28 /* Fixed by Erik Andersen to do passwords the tinylogin way...
29  * It now works with md5, sha1, etc passwords. */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <sys/vt.h>
34 #include <signal.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <errno.h>
39 #include <sys/ioctl.h>
40 #include <termios.h>
41
42 #include "busybox.h"
43
44 static struct passwd *pw;
45 static struct vt_mode ovtm;
46 static struct termios oterm;
47 static int vfd;
48 static unsigned long o_lock_all;
49
50 static void release_vt(int signo)
51 {
52         if (!o_lock_all)
53                 ioctl(vfd, VT_RELDISP, 1);
54         else
55                 ioctl(vfd, VT_RELDISP, 0);
56 }
57
58 static void acquire_vt(int signo)
59 {
60         ioctl(vfd, VT_RELDISP, VT_ACKACQ);
61 }
62
63 static void restore_terminal(void)
64 {
65         ioctl(vfd, VT_SETMODE, &ovtm);
66         tcsetattr(STDIN_FILENO, TCSANOW, &oterm);
67 }
68
69 int vlock_main(int argc, char **argv)
70 {
71         sigset_t sig;
72         struct sigaction sa;
73         struct vt_mode vtm;
74         struct termios term;
75
76         if (argc > 2) {
77                 bb_show_usage();
78         }
79
80         o_lock_all = bb_getopt_ulflags (argc, argv, "a");
81
82         if((pw = getpwuid(getuid())) == NULL) {
83                 bb_error_msg_and_die("Unknown uid %d", getuid());
84         }
85
86         vfd = bb_xopen(CURRENT_TTY, O_RDWR);
87
88         if (ioctl(vfd, VT_GETMODE, &vtm) < 0) {
89                 bb_perror_msg_and_die("VT_GETMODE");
90         }
91
92         /* mask a bunch of signals */
93         sigprocmask(SIG_SETMASK, NULL, &sig);
94         sigdelset(&sig, SIGUSR1);
95         sigdelset(&sig, SIGUSR2);
96         sigaddset(&sig, SIGTSTP);
97         sigaddset(&sig, SIGTTIN);
98         sigaddset(&sig, SIGTTOU);
99         sigaddset(&sig, SIGHUP);
100         sigaddset(&sig, SIGCHLD);
101         sigaddset(&sig, SIGQUIT);
102         sigaddset(&sig, SIGINT);
103
104         sigemptyset(&(sa.sa_mask));
105         sa.sa_flags = SA_RESTART;
106         sa.sa_handler = release_vt;
107         sigaction(SIGUSR1, &sa, NULL);
108         sa.sa_handler = acquire_vt;
109         sigaction(SIGUSR2, &sa, NULL);
110
111         /* need to handle some signals so that we don't get killed by them */
112         sa.sa_handler = SIG_IGN;
113         sigaction(SIGHUP, &sa, NULL);
114         sigaction(SIGQUIT, &sa, NULL);
115         sigaction(SIGINT, &sa, NULL);
116         sigaction(SIGTSTP, &sa, NULL);
117
118         ovtm = vtm;
119         vtm.mode = VT_PROCESS;
120         vtm.relsig = SIGUSR1;
121         vtm.acqsig = SIGUSR2;
122         ioctl(vfd, VT_SETMODE, &vtm);
123
124         tcgetattr(STDIN_FILENO, &oterm);
125         term = oterm;
126         term.c_iflag &= ~BRKINT;
127         term.c_iflag |= IGNBRK;
128         term.c_lflag &= ~ISIG;
129         term.c_lflag &= ~(ECHO | ECHOCTL);
130         tcsetattr(STDIN_FILENO, TCSANOW, &term);
131
132         do {
133                 printf("Virtual Console%s locked.\n%s's ", (o_lock_all) ? "s" : "", pw->pw_name);
134                 fflush(stdout);
135                 if (correct_password (pw)) {
136                         break;
137                 }
138                 bb_do_delay(FAIL_DELAY);
139                 puts("Password incorrect.");
140         } while (1);
141         restore_terminal();
142         return 0;
143 }
144
145 /*
146 Local Variables:
147 c-file-style: "linux"
148 c-basic-offset: 4
149 tab-width: 4
150 End:
151 */