1 /* console_switch.c -- console grabbing routines 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
14 #if !defined(__FreeBSD__) && !defined(_GNU_SOURCE)
23 #include <sys/ioctl.h>
27 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
28 #include <sys/consio.h>
33 #include "console_switch.h"
35 /* Is console switching currently disabled? */
36 bool console_switch_locked
= false;
38 /* This handler is called whenever a user tries to
39 * switch away from this virtual console. */
40 static void release_vt(int __attribute__ ((__unused__
)) signum
)
42 /* Deny console switch. */
43 (void) ioctl(STDIN_FILENO
, VT_RELDISP
, 0);
46 /* This handler is called whenever a user switches to this
48 static void acquire_vt(int __attribute__ ((__unused__
)) signum
)
50 /* Acknowledge console switch. */
51 (void) ioctl(STDIN_FILENO
, VT_RELDISP
, VT_ACKACQ
);
54 /* Console mode before switching was disabled. */
55 static struct vt_mode vtm
;
56 /* Signal actions before console handling was disabled. */
57 static struct sigaction sa_usr1
;
58 static struct sigaction sa_usr2
;
60 /* Disable virtual console switching in the kernel. If disabling fails false
61 * is returned and *error is set to a diagnostic message that must be freed by
63 bool lock_console_switch(char **error
)
65 /* Console mode when switching is disabled. */
66 struct vt_mode lock_vtm
;
69 /* Get the virtual console mode. */
70 if (ioctl(STDIN_FILENO
, VT_GETMODE
, &vtm
) < 0) {
71 if (errno
== ENOTTY
|| errno
== EINVAL
)
72 *error
= strdup("this terminal is not a virtual console");
74 (void) asprintf(error
, "could not get virtual console mode: %s", strerror(errno
));
79 /* Copy the current virtual console mode. */
82 (void) sigemptyset(&(sa
.sa_mask
));
83 sa
.sa_flags
= SA_RESTART
;
84 sa
.sa_handler
= release_vt
;
85 (void) sigaction(SIGUSR1
, &sa
, &sa_usr1
);
86 sa
.sa_handler
= acquire_vt
;
87 (void) sigaction(SIGUSR2
, &sa
, &sa_usr2
);
89 /* Set terminal switching to be process governed. */
90 lock_vtm
.mode
= VT_PROCESS
;
91 /* Set terminal release signal, i.e. sent when switching away. */
92 lock_vtm
.relsig
= SIGUSR1
;
93 /* Set terminal acquire signal, i.e. sent when switching here. */
94 lock_vtm
.acqsig
= SIGUSR2
;
95 /* Set terminal free signal, not implemented on either FreeBSD or Linux. */
96 /* Linux ignores this but FreeBSD wants a valid signal number here. */
97 lock_vtm
.frsig
= SIGHUP
;
99 /* Set virtual console mode to be process governed thus disabling console
100 * switching through the signal handlers above. */
101 if (ioctl(STDIN_FILENO
, VT_SETMODE
, &lock_vtm
) < 0) {
102 (void) asprintf(error
, "could not set virtual console mode: %s", strerror(errno
));
103 (void) sigaction(SIGUSR1
, &sa_usr1
, NULL
);
104 (void) sigaction(SIGUSR2
, &sa_usr2
, NULL
);
108 console_switch_locked
= true;
112 /* Reenable console switching if it was previously disabled. */
113 void unlock_console_switch(void)
115 /* Restore virtual console mode. */
116 if (console_switch_locked
) {
117 console_switch_locked
= (ioctl(STDIN_FILENO
, VT_SETMODE
, &vtm
) < 0);
119 if (console_switch_locked
) {
120 perror("could not restore virtual console mode");
122 (void) sigaction(SIGUSR1
, &sa_usr1
, NULL
);
123 (void) sigaction(SIGUSR2
, &sa_usr2
, NULL
);