1 /* openvt.c - Run a program on a new VT
2 *
3 * Copyright 2014 Vivek Kumar Bhagat <vivek.bhagat89@gmail.com>
4 *
5 * No Standard
6
7 USE_OPENVT(NEWTOY(openvt, "c#<1>63sw", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
8 USE_DEALLOCVT(NEWTOY(deallocvt, ">1", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NEEDROOT))
9
10 config OPENVT
11 bool "openvt"
12 default n
13 depends on TOYBOX_FORK
14 help
15 usage: openvt [-c NUM] [-sw] [COMMAND...]
16
17 Start a program on a new virtual terminal.
18
19 -c NUM Use VT NUM
20 -s Switch to new VT
21 -w Wait for command to exit
22
23 Together -sw switch back to originating VT when command completes.
24
25 config DEALLOCVT
26 bool "deallocvt"
27 default n
28 help
29 usage: deallocvt [NUM]
30
31 Deallocate unused virtual terminals, either a specific /dev/ttyNUM, or all.
32 */
33
34 #define FOR_openvt
35 #include "toys.h"
36 #include <linux/vt.h>
37 #include <linux/kd.h>
38
GLOBALS(long c;)39 GLOBALS(
40 long c;
41 )
42
43 int open_console(void)
44 {
45 char arg = 0, *console_name[] = {"/dev/tty", "/dev/tty0", "/dev/console"};
46 int i, fd;
47
48 for (i = 0; i < ARRAY_LEN(console_name); i++) {
49 if (0>(fd = open(console_name[i], O_RDWR))) continue;
50 if (!ioctl(fd, KDGKBTYPE, &arg)) return fd;
51 close(fd);
52 }
53 for (fd = 0; fd < 3; fd++) if (!ioctl(fd, KDGKBTYPE, &arg)) return fd;
54 error_exit("can't open console");
55 }
56
openvt_main(void)57 void openvt_main(void)
58 {
59 struct vt_stat vstate;
60 int fd;
61 pid_t pid;
62
63 // find current console
64 if (-1 == (ioctl(fd = open_console(), VT_GETSTATE, &vstate)) ||
65 (!TT.c && 0>=(TT.c = xioctl(fd, VT_OPENQRY, &fd))))
66 perror_exit("can't find open VT");
67
68 sprintf(toybuf, "/dev/tty%ld", TT.c);
69 close(0); //new vt becomes stdin
70 dup2(dup2(xopen_stdio(toybuf, O_RDWR), 1), 2);
71 if (FLAG(s)) {
72 ioctl(0, VT_ACTIVATE, (int)TT.c);
73 ioctl(0, VT_WAITACTIVE, (int)TT.c);
74 }
75
76 if (!(pid = xfork())) {
77 setsid();
78 ioctl(0, TIOCSCTTY, 0);
79 if (fd>2) close(fd);
80 xexec(toys.optargs);
81 }
82
83 if (FLAG(w)) {
84 while (-1 == waitpid(pid, NULL, 0) && errno == EINTR);
85 if (FLAG(s)) {
86 ioctl(fd, VT_ACTIVATE, vstate.v_active);
87 ioctl(fd, VT_WAITACTIVE, vstate.v_active);
88 ioctl(fd, VT_DISALLOCATE, (int)TT.c);
89 }
90 }
91 close(fd);
92 }
93
deallocvt_main(void)94 void deallocvt_main(void)
95 {
96 int fd, vt_num = 0; // 0 = all
97
98 if (*toys.optargs) vt_num = atolx_range(*toys.optargs, 1, 63);
99 if (-1 == ioctl(fd = open_console(), VT_DISALLOCATE, vt_num))
100 perror_exit("%d", vt_num);
101 close(fd);
102 }
103