|
Packit |
ec106e |
|
|
Packit |
ec106e |
/*
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
VT code and signal handling for vlock, the VT locking program for linux.
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
Copyright (C) 1994-1998 Michael K. Johnson <johnsonm@redhat.com>
|
|
Packit |
ec106e |
Copyright (C) 2002, 2004, 2005 Dmitry V. Levin <ldv@altlinux.org>
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
This program is free software; you can redistribute it and/or modify
|
|
Packit |
ec106e |
it under the terms of the GNU General Public License as published by
|
|
Packit |
ec106e |
the Free Software Foundation; either version 2 of the License, or
|
|
Packit |
ec106e |
(at your option) any later version.
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
This program is distributed in the hope that it will be useful,
|
|
Packit |
ec106e |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
ec106e |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
ec106e |
GNU General Public License for more details.
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
You should have received a copy of the GNU General Public License
|
|
Packit |
ec106e |
along with this program; if not, write to the Free Software
|
|
Packit |
ec106e |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
Packit |
ec106e |
*/
|
|
Packit |
ec106e |
#include "config.h"
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
#include <stdio.h>
|
|
Packit |
ec106e |
#include <errno.h>
|
|
Packit |
ec106e |
#include <string.h>
|
|
Packit |
ec106e |
#include <stdlib.h>
|
|
Packit |
ec106e |
#include <unistd.h>
|
|
Packit |
ec106e |
#include <fcntl.h>
|
|
Packit |
ec106e |
#include <signal.h>
|
|
Packit |
ec106e |
#include <sys/vt.h>
|
|
Packit |
ec106e |
#include <sys/ioctl.h>
|
|
Packit |
ec106e |
#include <sys/wait.h>
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
#include "vlock.h"
|
|
Packit |
ec106e |
#include "nls.h"
|
|
Packit |
ec106e |
#include "kbd_error.h"
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/* Saved VT mode. */
|
|
Packit |
ec106e |
struct vt_mode ovtm;
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/* VT descriptor. */
|
|
Packit |
ec106e |
static int vfd = -1;
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/* Copy of the VT mode when the program was started. */
|
|
Packit |
ec106e |
int is_vt;
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/*
|
|
Packit |
ec106e |
* This is called by a signal whenever a user tries to change
|
|
Packit |
ec106e |
* the VC (with a ALT-Fn key or via VT_ACTIVATE).
|
|
Packit |
ec106e |
*/
|
|
Packit |
ec106e |
static void
|
|
Packit |
ec106e |
release_vt(__attribute__((unused)) int signo)
|
|
Packit |
ec106e |
{
|
|
Packit |
ec106e |
/*
|
|
Packit |
ec106e |
* Kernel is not allowed to switch.
|
|
Packit |
ec106e |
* Return code is silently ignored.
|
|
Packit |
ec106e |
*/
|
|
Packit |
ec106e |
ioctl(vfd, VT_RELDISP, 0);
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/* This is called whenever a user switches to that VC. */
|
|
Packit |
ec106e |
static void
|
|
Packit |
ec106e |
acquire_vt(__attribute__((unused)) int signo)
|
|
Packit |
ec106e |
{
|
|
Packit |
ec106e |
/*
|
|
Packit |
ec106e |
* This call is not currently required under Linux,
|
|
Packit |
ec106e |
* but it won't hurt, either.
|
|
Packit |
ec106e |
* Return code is silently ignored.
|
|
Packit |
ec106e |
*/
|
|
Packit |
ec106e |
ioctl(vfd, VT_RELDISP, VT_ACKACQ);
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/* Set the signal masks and handlers. */
|
|
Packit |
ec106e |
static void
|
|
Packit |
ec106e |
mask_signals(void)
|
|
Packit |
ec106e |
{
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
static sigset_t sig;
|
|
Packit |
ec106e |
static struct sigaction sa;
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
memset(&sa, 0, sizeof sa);
|
|
Packit |
ec106e |
sigemptyset(&(sa.sa_mask));
|
|
Packit |
ec106e |
sa.sa_flags = SA_RESTART;
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
if (o_lock_all) {
|
|
Packit |
ec106e |
/* handle SIGUSR{1,2}... */
|
|
Packit |
ec106e |
sa.sa_handler = release_vt;
|
|
Packit |
ec106e |
sigaction(SIGUSR1, &sa, 0);
|
|
Packit |
ec106e |
sa.sa_handler = acquire_vt;
|
|
Packit |
ec106e |
sigaction(SIGUSR2, &sa, 0);
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/* ... and ensure they are unblocked. */
|
|
Packit |
ec106e |
sigemptyset(&sig);
|
|
Packit |
ec106e |
sigaddset(&sig, SIGUSR1);
|
|
Packit |
ec106e |
sigaddset(&sig, SIGUSR2);
|
|
Packit |
ec106e |
sigprocmask(SIG_UNBLOCK, &sig, 0);
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/* Ignore all the rest. */
|
|
Packit |
ec106e |
sa.sa_handler = SIG_IGN;
|
|
Packit |
ec106e |
if (!o_lock_all) {
|
|
Packit |
ec106e |
sigaction(SIGUSR1, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGUSR2, &sa, 0);
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
sigaction(SIGHUP, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGINT, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGQUIT, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGPIPE, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGALRM, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGTERM, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGTSTP, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGTTIN, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGTTOU, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGURG, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGVTALRM, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGIO, &sa, 0);
|
|
Packit |
ec106e |
sigaction(SIGPWR, &sa, 0);
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/*
|
|
Packit |
ec106e |
* Also block SIGCHLD.
|
|
Packit |
ec106e |
* Not really needed; just make sleep(3) more easy.
|
|
Packit |
ec106e |
*/
|
|
Packit |
ec106e |
sigemptyset(&sig);
|
|
Packit |
ec106e |
sigaddset(&sig, SIGCHLD);
|
|
Packit |
ec106e |
sigprocmask(SIG_BLOCK, &sig, 0);
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
int init_vt(const char *tty)
|
|
Packit |
ec106e |
{
|
|
Packit |
ec106e |
const char dev_tty[] = "/dev/tty";
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
vfd = open(dev_tty, O_RDWR);
|
|
Packit |
ec106e |
if (vfd < 0) {
|
|
Packit |
ec106e |
kbd_warning(errno, "could not open %s", dev_tty);
|
|
Packit |
ec106e |
return 0;
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/*
|
|
Packit |
ec106e |
* First we will set process control of VC switching.
|
|
Packit |
ec106e |
* - If this fails, then we know that we aren't on a VC,
|
|
Packit |
ec106e |
* and will print a warning message.
|
|
Packit |
ec106e |
* - If it doesn't fail, it gets the current VT status.
|
|
Packit |
ec106e |
*/
|
|
Packit |
ec106e |
if (ioctl(vfd, VT_GETMODE, &ovtm) < 0) {
|
|
Packit |
ec106e |
is_vt = 0;
|
|
Packit |
ec106e |
fprintf(stderr, _("This tty (%s) is not a virtual console.\n"),
|
|
Packit |
ec106e |
tty);
|
|
Packit |
ec106e |
if (o_lock_all) {
|
|
Packit |
ec106e |
o_lock_all = 0;
|
|
Packit |
ec106e |
close(vfd);
|
|
Packit |
ec106e |
vfd = -1;
|
|
Packit |
ec106e |
fprintf(stderr,
|
|
Packit |
ec106e |
_("The entire console display cannot be locked.\n"));
|
|
Packit |
ec106e |
return 0;
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
fprintf(stderr, "\n\n");
|
|
Packit |
ec106e |
fflush(stderr);
|
|
Packit |
ec106e |
} else {
|
|
Packit |
ec106e |
is_vt = 1;
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/* If we aren't going to lock console, we don't need VT descriptor. */
|
|
Packit |
ec106e |
if (!o_lock_all) {
|
|
Packit |
ec106e |
close(vfd);
|
|
Packit |
ec106e |
vfd = -1;
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
mask_signals();
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
if (o_lock_all) {
|
|
Packit |
ec106e |
struct vt_mode vtm = ovtm;
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
vtm.mode = VT_PROCESS; /* Process controls switching. */
|
|
Packit |
ec106e |
vtm.relsig = SIGUSR1; /* Signal to raise on release request, handled by release_vt(). */
|
|
Packit |
ec106e |
vtm.acqsig = SIGUSR2; /* Signal to raise on acquisition, handled by acquire_vt(). */
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
/* Set mode of active vt. */
|
|
Packit |
ec106e |
if (ioctl(vfd, VT_SETMODE, &vtm) < 0) {
|
|
Packit |
ec106e |
kbd_warning(errno, "ioctl VT_SETMODE");
|
|
Packit |
ec106e |
return 0;
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
if (is_vt)
|
|
Packit |
ec106e |
init_screen();
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
return 1;
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
void restore_vt(void)
|
|
Packit |
ec106e |
{
|
|
Packit |
ec106e |
if (is_vt) {
|
|
Packit |
ec106e |
restore_screen();
|
|
Packit |
ec106e |
|
|
Packit |
ec106e |
if (o_lock_all) {
|
|
Packit |
ec106e |
/*
|
|
Packit |
ec106e |
* Reset mode of active vt.
|
|
Packit |
ec106e |
* Don't check return code - it won't help anyway.
|
|
Packit |
ec106e |
*/
|
|
Packit |
ec106e |
ioctl(vfd, VT_SETMODE, &ovtm);
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
}
|
|
Packit |
ec106e |
}
|