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