1
/* vlock-main.c -- main routine for vlock,
2
* the VT locking program for linux
4
* This program is copyright (C) 2007 Frank Benkstein, and is free
5
* software which is freely distributable under the terms of the
6
* GNU General Public License version 2, included as the file COPYING in this
7
* distribution. It is NOT public domain software, and any
8
* redistribution not permitted by the GNU General Public License is
9
* expressly forbidden without prior written permission from
22
#include <sys/types.h>
29
#include "console_switch.h"
38
#define ensure_atexit(func) \
40
if (atexit(func) != 0) \
41
fatal_perror("vlock: atexit() failed"); \
44
static char *get_username(void)
47
char *username = NULL;
49
/* Get the user name from the environment if started as root. */
51
username = getenv("USER");
53
if (username == NULL) {
56
/* Get the password entry. */
62
username = pw->pw_name;
65
return strdup(username);
68
static void terminate(int signum)
70
fprintf(stderr, "vlock: Terminated!\n");
71
/* Call exit here to ensure atexit handlers are called. */
75
static void block_signals(void)
79
/* Ignore some signals. */
80
/* These signals shouldn't be delivered anyway, because terminal signals are
82
(void) sigemptyset(&(sa.sa_mask));
83
sa.sa_flags = SA_RESTART;
84
sa.sa_handler = SIG_IGN;
85
(void) sigaction(SIGINT, &sa, NULL);
86
(void) sigaction(SIGQUIT, &sa, NULL);
87
(void) sigaction(SIGTSTP, &sa, NULL);
89
/* Install special handler for SIGTERM. */
90
sa.sa_flags = SA_RESETHAND;
91
sa.sa_handler = terminate;
92
(void) sigaction(SIGTERM, &sa, NULL);
95
static struct termios term;
96
static tcflag_t lflag;
98
static void secure_terminal(void)
100
/* Disable terminal echoing and signals. */
101
(void) tcgetattr(STDIN_FILENO, &term);
102
lflag = term.c_lflag;
103
term.c_lflag &= ~(ECHO | ISIG);
104
(void) tcsetattr(STDIN_FILENO, TCSANOW, &term);
107
static void restore_terminal(void)
109
/* Restore the terminal. */
110
term.c_lflag = lflag;
111
(void) tcsetattr(STDIN_FILENO, TCSANOW, &term);
114
static int auth_tries;
116
static void auth_loop(const char *username)
118
struct timespec *prompt_timeout;
119
struct timespec *wait_timeout;
122
/* Get the vlock message from the environment. */
123
vlock_message = getenv("VLOCK_MESSAGE");
125
if (vlock_message == NULL) {
126
if (console_switch_locked)
127
vlock_message = getenv("VLOCK_ALL_MESSAGE");
129
vlock_message = getenv("VLOCK_CURRENT_MESSAGE");
132
/* Get the timeouts from the environment. */
133
prompt_timeout = parse_seconds(getenv("VLOCK_PROMPT_TIMEOUT"));
135
wait_timeout = parse_seconds(getenv("VLOCK_TIMEOUT"));
143
/* Print vlock message if there is one. */
144
if (vlock_message && *vlock_message) {
145
fputs(vlock_message, stderr);
149
/* Wait for enter or escape to be pressed. */
150
c = wait_for_character("\n\033", wait_timeout);
152
/* Escape was pressed or the timeout occurred. */
153
if (c == '\033' || c == 0) {
155
plugin_hook("vlock_save");
156
/* Wait for any key to be pressed. */
157
c = wait_for_character(NULL, NULL);
158
plugin_hook("vlock_save_abort");
160
/* Do not require enter to be pressed twice. */
168
/* Try authentication as user. */
169
if (auth(username, prompt_timeout))
175
if (strcmp(username, "root") != 0) {
176
/* Try authentication as root. */
177
if (auth("root", prompt_timeout))
187
/* Free timeouts memory. */
189
free(prompt_timeout);
192
void display_auth_tries(void)
195
fprintf(stderr, "%d failed authentication %s.\n", auth_tries, auth_tries > 1 ? "tries" : "try");
199
static void call_end_hook(void)
201
(void) plugin_hook("vlock_end");
205
/* Lock the current terminal until proper authentication is received. */
206
int main(int argc, char *const argv[])
210
vlock_debug = (getenv("VLOCK_DEBUG") != NULL);
214
username = get_username();
216
if (username == NULL)
217
fatal_perror("vlock: could not get username");
219
ensure_atexit(display_auth_tries);
222
for (int i = 1; i < argc; i++)
223
if (!load_plugin(argv[i]))
224
fatal_error("vlock: loading plugin '%s' failed: %s", argv[i], STRERROR);
226
ensure_atexit(unload_plugins);
228
if (!resolve_dependencies()) {
232
fatal_error("vlock: error resolving plugin dependencies: %s", STRERROR);
235
plugin_hook("vlock_start");
236
ensure_atexit(call_end_hook);
237
#else /* !USE_PLUGINS */
238
/* Emulate pseudo plugin "all". */
239
if (argc == 2 && (strcmp(argv[1], "all") == 0)) {
240
if (!lock_console_switch()) {
242
perror("vlock: could not disable console switching");
247
ensure_atexit((void (*)(void))unlock_console_switch);
248
} else if (argc > 1) {
249
fatal_error("vlock: plugin support disabled");
253
if (!isatty(STDIN_FILENO))
254
fatal_error("vlock: stdin is not a terminal");
257
ensure_atexit(restore_terminal);