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");
74 static void block_signals(void)
78 /* Ignore some signals. */
79 /* These signals shouldn't be delivered anyway, because terminal signals are
81 (void) sigemptyset(&(sa
.sa_mask
));
82 sa
.sa_flags
= SA_RESTART
;
83 sa
.sa_handler
= SIG_IGN
;
84 (void) sigaction(SIGINT
, &sa
, NULL
);
85 (void) sigaction(SIGQUIT
, &sa
, NULL
);
86 (void) sigaction(SIGTSTP
, &sa
, NULL
);
88 /* Install special handler for SIGTERM. */
89 sa
.sa_flags
= SA_RESETHAND
;
90 sa
.sa_handler
= terminate
;
91 (void) sigaction(SIGTERM
, &sa
, NULL
);
94 static struct termios term
;
95 static tcflag_t lflag
;
97 static void secure_terminal(void)
99 /* Disable terminal echoing and signals. */
100 (void) tcgetattr(STDIN_FILENO
, &term
);
101 lflag
= term
.c_lflag
;
102 term
.c_lflag
&= ~(ECHO
| ISIG
);
103 (void) tcsetattr(STDIN_FILENO
, TCSANOW
, &term
);
106 static void restore_terminal(void)
108 /* Restore the terminal. */
109 term
.c_lflag
= lflag
;
110 (void) tcsetattr(STDIN_FILENO
, TCSANOW
, &term
);
113 static int auth_tries
;
115 static void auth_loop(const char *username
)
117 struct timespec
*prompt_timeout
;
118 struct timespec
*wait_timeout
;
121 /* Get the vlock message from the environment. */
122 vlock_message
= getenv("VLOCK_MESSAGE");
124 if (vlock_message
== NULL
) {
125 if (console_switch_locked
)
126 vlock_message
= getenv("VLOCK_ALL_MESSAGE");
128 vlock_message
= getenv("VLOCK_CURRENT_MESSAGE");
131 /* Get the timeouts from the environment. */
132 prompt_timeout
= parse_seconds(getenv("VLOCK_PROMPT_TIMEOUT"));
134 wait_timeout
= parse_seconds(getenv("VLOCK_TIMEOUT"));
142 /* Print vlock message if there is one. */
143 if (vlock_message
&& *vlock_message
) {
144 fputs(vlock_message
, stderr
);
148 /* Wait for enter or escape to be pressed. */
149 c
= wait_for_character("\n\033", wait_timeout
);
151 /* Escape was pressed or the timeout occurred. */
152 if (c
== '\033' || c
== 0) {
154 plugin_hook("vlock_save");
155 /* Wait for any key to be pressed. */
156 c
= wait_for_character(NULL
, NULL
);
157 plugin_hook("vlock_save_abort");
159 /* Do not require enter to be pressed twice. */
167 /* Try authentication as user. */
168 if (auth(username
, prompt_timeout
))
174 if (strcmp(username
, "root") != 0) {
175 /* Try authentication as root. */
176 if (auth("root", prompt_timeout
))
186 /* Free timeouts memory. */
188 free(prompt_timeout
);
191 void display_auth_tries(void)
194 fprintf(stderr
, "%d failed authentication %s.\n", auth_tries
, auth_tries
> 1 ? "tries" : "try");
198 static void call_end_hook(void)
200 (void) plugin_hook("vlock_end");
204 /* Lock the current terminal until proper authentication is received. */
205 int main(int argc
, char *const argv
[])
209 vlock_debug
= (getenv("VLOCK_DEBUG") != NULL
);
213 username
= get_username();
215 if (username
== NULL
)
216 fatal_perror("vlock: could not get username");
218 ensure_atexit(display_auth_tries
);
221 for (int i
= 1; i
< argc
; i
++)
222 if (!load_plugin(argv
[i
]))
223 fatal_error("vlock: loading plugin '%s' failed: %s", argv
[i
], STRERROR
);
225 ensure_atexit(unload_plugins
);
227 if (!resolve_dependencies()) {
231 fatal_error("vlock: error resolving plugin dependencies: %s", STRERROR
);
234 plugin_hook("vlock_start");
235 ensure_atexit(call_end_hook
);
236 #else /* !USE_PLUGINS */
237 /* Emulate pseudo plugin "all". */
238 if (argc
== 2 && (strcmp(argv
[1], "all") == 0)) {
239 if (!lock_console_switch()) {
241 perror("vlock: could not disable console switching");
246 ensure_atexit((void (*)(void))unlock_console_switch
);
247 } else if (argc
> 1) {
248 fatal_error("vlock: plugin support disabled");
252 if (!isatty(STDIN_FILENO
))
253 fatal_error("vlock: stdin is not a terminal");
256 ensure_atexit(restore_terminal
);