• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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