1 /* vlock-new.c -- console allocation 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
18 #include <sys/ioctl.h>
20 #include <sys/types.h>
23 #include <sys/consio.h>
26 #endif /* __FreeBSD__ */
30 /* Get the currently active console from the given
31 * console file descriptor. Returns console number
32 * (starting from 1) on success, -1 on error. */
34 static int get_active_console(int consfd
) {
37 if (ioctl(consfd
, VT_GETACTIVE
, &n
) == 0)
43 static int get_active_console(int consfd
) {
44 struct vt_stat vtstate
;
46 /* get the virtual console status */
47 if (ioctl(consfd
, VT_GETSTATE
, &vtstate
) == 0)
48 return vtstate
.v_active
;
54 /* Get the device name for the given console number.
55 * Returns the device name or NULL on error. */
56 static char *get_console_name(int n
) {
57 static char name
[sizeof VTNAME
+ 2];
63 /* format the virtual terminal filename from the number */
65 namelen
= snprintf(name
, sizeof name
, VTNAME
, n
-1);
67 namelen
= snprintf(name
, sizeof name
, VTNAME
, n
);
70 if (namelen
> sizeof name
) {
71 fprintf(stderr
, "vlock-new: virtual terminal number too large\n");
79 /* Run vlock-all on a new console. */
81 int consfd
= STDIN_FILENO
;
89 /* get the number of the currently active console */
90 old_vtno
= get_active_console(consfd
);
93 /* stdin is does not a virtual console */
96 /* XXX: add optional PAM check here */
98 /* open the virtual console directly */
99 if ((consfd
= open(CONSOLE
, O_RDWR
)) < 0) {
100 perror("vlock-new: cannot open virtual console");
104 /* get the number of the currently active console, again */
105 old_vtno
= get_active_console(consfd
);
108 perror("vlock-new: could not find out currently active console");
113 /* get a free virtual terminal number */
114 if (ioctl(consfd
, VT_OPENQRY
, &vtno
) < 0) {
115 perror("vlock-new: could not find a free virtual terminal");
119 /* get the device name for the new virtual console */
120 vtname
= get_console_name(vtno
);
122 /* open the free virtual terminal */
123 if ((vtfd
= open(vtname
, O_RDWR
)) < 0) {
124 perror("vlock-new: cannot open new console");
128 /* switch to the virtual terminal */
129 if (ioctl(consfd
, VT_ACTIVATE
, vtno
) < 0
130 || ioctl(consfd
, VT_WAITACTIVE
, vtno
) < 0) {
131 perror("vlock-new: could not activate new terminal");
140 /* close the virtual console file descriptor */
141 (void) close(consfd
);
144 (void) setuid(getuid());
146 /* make this process a session leader */
149 /* make new virtual terminal controlling tty of this process */
150 if (ioctl(vtfd
, TIOCSCTTY
, 1) < 0) {
151 perror("vlock-new: could not set controlling terminal");
156 dup2(vtfd
, STDIN_FILENO
);
157 dup2(vtfd
, STDOUT_FILENO
);
158 dup2(vtfd
, STDERR_FILENO
);
162 execl(VLOCK_ALL
, VLOCK_ALL
, (char *) NULL
);
163 perror("vlock-new: exec of vlock-all failed");
165 } else if (pid
< 0) {
166 perror("vlock-new: could not create child process");
169 /* close virtual terminal file descriptor */
172 if (pid
> 0 && waitpid(pid
, &status
, 0) < 0) {
173 perror("vlock-new: child process missing");
177 /* switch back to former virtual terminal */
178 if (ioctl(consfd
, VT_ACTIVATE
, old_vtno
) < 0
179 || ioctl(consfd
, VT_WAITACTIVE
, old_vtno
) < 0)
180 perror("vlock-new: could not activate previous console");
183 /* deallocate virtual terminal */
184 if (ioctl(consfd
, VT_DISALLOCATE
, vtno
) < 0)
185 perror("vlock-new: could not disallocate console");
188 (void) close(consfd
);
190 /* exit with the exit status of the child or 128+signal if it was killed */
192 if (WIFEXITED(status
))
193 exit (WEXITSTATUS(status
));
194 else if (WIFSIGNALED(status
))
195 exit (128+WTERMSIG(status
));