1 /* openvt.c - Run a program on a new VT
2 *
3 * Copyright 2008 David Anders <[email protected]>
4 * Copyright 2014 Vivek Kumar Bhagat <[email protected]>
5 *
6 * No Standard
7
8 USE_OPENVT(NEWTOY(openvt, "^<1c#<1>63sw", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
9 USE_CHVT(NEWTOY(chvt, "<1>1", TOYFLAG_USR|TOYFLAG_BIN))
10 USE_DEALLOCVT(NEWTOY(deallocvt, ">1", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NEEDROOT))
11
12 config OPENVT
13 bool "openvt"
14 default y
15 help
16 usage: openvt [-c NUM] [-sw] COMMAND...
17
18 Run COMMAND on a new virtual terminal.
19
20 -c NUM Use VT NUM
21 -s Switch to the new VT
22 -w Wait for command to exit (with -s, deallocates VT on exit)
23
24 config CHVT
25 bool "chvt"
26 default y
27 help
28 usage: chvt NUM
29
30 Change to virtual terminal number NUM. (This only works in text mode.)
31
32 Virtual terminals are the Linux VGA text mode (or framebuffer) displays,
33 switched between via alt-F1, alt-F2, etc. Use ctrl-alt-F1 to switch
34 from X11 to a virtual terminal, and alt-F6 (or F7, or F8) to get back.
35
36 config DEALLOCVT
37 bool "deallocvt"
38 default y
39 help
40 usage: deallocvt [NUM]
41
42 Deallocate unused virtual terminals, either a specific /dev/ttyNUM, or all.
43 */
44
45 #define FOR_openvt
46 #include "toys.h"
47 #include <linux/vt.h>
48 #include <linux/kd.h>
49
GLOBALS(long c;)50 GLOBALS(
51 long c;
52 )
53
54 static int open_console(void)
55 {
56 char arg = 0, *console_name[] = {"/dev/tty", "/dev/tty0", "/dev/console"};
57 int i, fd;
58
59 for (i = 0; i < ARRAY_LEN(console_name); i++) {
60 if (0>(fd = open(console_name[i], O_RDWR))) continue;
61 if (!ioctl(fd, KDGKBTYPE, &arg)) return fd;
62 close(fd);
63 }
64 for (fd = 0; fd < 3; fd++) if (!ioctl(fd, KDGKBTYPE, &arg)) return fd;
65 error_exit("can't open console");
66 }
67
activate(int fd,int cc)68 static int activate(int fd, int cc)
69 {
70 return ioctl(fd, VT_ACTIVATE, cc) || ioctl(fd, VT_WAITACTIVE, cc);
71 }
72
openvt_main(void)73 void openvt_main(void)
74 {
75 struct vt_stat vstate;
76 int fd, cc = (int)TT.c;
77 pid_t pid;
78
79 // find current console
80 if (-1 == (ioctl(fd = open_console(), VT_GETSTATE, &vstate)) ||
81 (!cc && 0>=(cc = xioctl(fd, VT_OPENQRY, &fd))))
82 perror_exit("can't find open VT");
83
84 sprintf(toybuf, "/dev/tty%d", cc);
85 if (!(pid = XVFORK())) {
86 close(0); //new vt becomes stdin
87 dup2(dup2(xopen_stdio(toybuf, O_RDWR), 1), 2);
88 if (FLAG(s)) activate(0, cc);
89 setsid();
90 ioctl(0, TIOCSCTTY, 0);
91 if (fd>2) close(fd);
92 xexec(toys.optargs);
93 }
94 if (FLAG(w)) {
95 while (-1 == waitpid(pid, NULL, 0) && errno == EINTR) errno = 0;
96 if (FLAG(s)) {
97 activate(fd, vstate.v_active);
98 dprintf(2, "%d\n", ioctl(fd, VT_DISALLOCATE, cc));
99 }
100 }
101 }
102
chvt_main(void)103 void chvt_main(void)
104 {
105 if (activate(open_console(), atoi(*toys.optargs)))
106 perror_exit_raw(*toys.optargs);
107 }
108
deallocvt_main(void)109 void deallocvt_main(void)
110 {
111 int fd = open_console(), vt_num = 0; // 0 = all
112
113 if (*toys.optargs) vt_num = atolx_range(*toys.optargs, 1, 63);
114 if (-1 == ioctl(fd, VT_DISALLOCATE, vt_num)) perror_exit("%d", vt_num);
115 }
116