xref: /aosp_15_r20/external/toybox/toys/other/openvt.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
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