fix build on Debian/kFreeBSD
[vlock.git] / src / vlock-all.c
blob22da509696bf5665294c6e58f33b8a7792eb803e
1 /* vlock-all.c -- console grabbing 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
10 * the author.
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <sys/ioctl.h>
19 #include <sys/wait.h>
20 #include <errno.h>
21 #include <signal.h>
23 #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
24 #include <sys/consio.h>
25 #else
26 #include <sys/vt.h>
27 #endif /* __FreeBSD__, __FreeBSD_kernel__ */
29 #include "vlock.h"
31 /* This handler is called by a signal whenever a user tries to
32 * switch away from this virtual console. */
33 void release_vt(int __attribute__((__unused__)) signum) {
34 /* kernel is not allowed to switch */
35 ioctl(STDIN_FILENO, VT_RELDISP, 0);
38 /* This handler is called whenever a user switches to this
39 * virtual console. */
40 void acquire_vt(int __attribute__((__unused__)) signum) {
41 /* acknowledge, this is a noop */
42 ioctl(STDIN_FILENO, VT_RELDISP, VT_ACKACQ);
45 /* Disable console switching while running vlock-current. */
46 int main(void) {
47 struct vt_mode vtmode, vtmode_bak;
48 struct sigaction sa;
49 int pid;
50 int status;
52 /* get the virtual console mode */
53 if (ioctl(STDIN_FILENO, VT_GETMODE, &vtmode) < 0) {
54 if (errno == ENOTTY || errno == EINVAL)
55 fprintf(stderr, "vlock-all: this terminal is not a virtual console\n");
56 else
57 perror("vlock-all: could not get virtual console mode");
59 exit (111);
62 (void) sigemptyset(&(sa.sa_mask));
63 sa.sa_flags = SA_RESTART;
64 sa.sa_handler = release_vt;
65 (void) sigaction(SIGUSR1, &sa, NULL);
66 sa.sa_handler = acquire_vt;
67 (void) sigaction(SIGUSR2, &sa, NULL);
69 /* back up current terminal mode */
70 vtmode_bak = vtmode;
71 /* set terminal switching to be process governed */
72 vtmode.mode = VT_PROCESS;
73 /* set terminal release signal, i.e. sent when switching away */
74 vtmode.relsig = SIGUSR1;
75 /* set terminal acquire signal, i.e. sent when switching here */
76 vtmode.acqsig = SIGUSR2;
77 /* set terminal free signal, not implemented on either FreeBSD or Linux */
78 /* Linux ignores it but FreeBSD wants a valid signal number here */
79 vtmode.frsig = SIGHUP;
81 /* set virtual console mode to be process governed
82 * thus disabling console switching */
83 if (ioctl(STDIN_FILENO, VT_SETMODE, &vtmode) < 0) {
84 perror("vlock-all: could not set virtual console mode");
85 exit (111);
88 pid = fork();
90 if (pid == 0) {
91 /* child */
93 /* drop privleges */
94 (void) setuid(getuid());
96 /* run child */
97 execl(VLOCK_CURRENT, VLOCK_CURRENT, (char *) NULL);
98 perror("vlock-all: exec of vlock-current failed");
99 _exit(127);
100 } else if (pid < 0) {
101 perror("vlock-all: could not create child process");
104 if (pid > 0 && waitpid(pid, &status, 0) < 0) {
105 perror("vlock-all: child process missing");
106 pid = -1;
109 /* globally enable virtual console switching */
110 if (ioctl(STDIN_FILENO, VT_SETMODE, &vtmode_bak) < 0)
111 perror("vlock-all: could not restore console mode");
113 /* exit with the exit status of the child or 128+signal if it was killed */
114 if (pid > 0) {
115 if (WIFEXITED(status))
116 exit (WEXITSTATUS(status));
117 else if (WIFSIGNALED(status))
118 exit (128+WTERMSIG(status));
121 return 0;