Blame src/vlock/vt.c

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