src/vlock.sh: fall back to old option parsing if gnu getopt is not available
[vlock.git] / src / vlock-all.c
blobd22b3830e6322bba132c1fd2bb3f28a102b20814
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 #ifdef __FreeBSD__
24 #include <sys/consio.h>
25 #else
26 #include <sys/vt.h>
27 #endif /* __FreeBSD__ */
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 int pid;
49 int status;
51 /* get the virtual console mode */
52 if (ioctl(STDIN_FILENO, VT_GETMODE, &vtmode) < 0) {
53 if (errno == ENOTTY || errno == EINVAL)
54 fprintf(stderr, "vlock-all: this terminal is not a virtual console\n");
55 else
56 perror("vlock-all: could not get virtual console mode");
58 exit (111);
61 /* back up current terminal mode */
62 vtmode_bak = vtmode;
63 /* set terminal switching to be process governed */
64 vtmode.mode = VT_PROCESS;
65 /* set terminal release signal, i.e. sent when switching away */
66 vtmode.relsig = SIGUSR1;
67 /* set terminal acquire signal, i.e. sent when switching here */
68 vtmode.acqsig = SIGUSR2;
69 /* set terminal free signal, not implemented on either FreeBSD or Linux */
70 /* Linux ignores it but FreeBSD wants a valid signal number here */
71 vtmode.frsig = SIGHUP;
73 /* set console switching signal handlers */
74 if (signal(SIGUSR1, release_vt) == SIG_ERR
75 || signal(SIGUSR2, acquire_vt) == SIG_ERR) {
76 perror("vlock-all: could not install signal handlers");
77 exit (111);
80 /* set virtual console mode to be process governed
81 * thus disabling console switching */
82 if (ioctl(STDIN_FILENO, VT_SETMODE, &vtmode) < 0) {
83 perror("vlock-all: could not set virtual console mode");
84 exit (111);
87 pid = fork();
89 if (pid == 0) {
90 /* child */
92 /* drop privleges */
93 (void) setuid(getuid());
95 /* run child */
96 execl(VLOCK_CURRENT, VLOCK_CURRENT, (char *) NULL);
97 perror("vlock-all: exec of vlock-current failed");
98 _exit(127);
99 } else if (pid < 0) {
100 perror("vlock-all: could not create child process");
103 if (pid > 0 && waitpid(pid, &status, 0) < 0) {
104 perror("vlock-all: child process missing");
105 pid = -1;
108 /* globally enable virtual console switching */
109 if (ioctl(STDIN_FILENO, VT_SETMODE, &vtmode_bak) < 0)
110 perror("vlock-all: could not restore console mode");
112 /* exit with the exit status of the child or 128+signal if it was killed */
113 if (pid > 0) {
114 if (WIFEXITED(status))
115 exit (WEXITSTATUS(status));
116 else if (WIFSIGNALED(status))
117 exit (128+WTERMSIG(status));
120 return 0;