1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34#define FOR_openvt
35#include "toys.h"
36#include <linux/vt.h>
37#include <linux/kd.h>
38
39GLOBALS(
40 unsigned long vt_num;
41)
42
43int open_console(void)
44{
45 char arg, *console_name[] = {"/dev/tty", "/dev/tty0", "/dev/console"};
46 int i, fd;
47
48 for (i = 0; i < ARRAY_LEN(console_name); i++) {
49 fd = open(console_name[i], O_RDWR);
50 if (fd >= 0) {
51 arg = 0;
52 if (!ioctl(fd, KDGKBTYPE, &arg)) return fd;
53 close(fd);
54 }
55 }
56
57
58 for (fd = 0; fd < 3; fd++) {
59 arg = 0;
60 if (0 == ioctl(fd, KDGKBTYPE, &arg)) return fd;
61 }
62
63 return -1;
64}
65
66int xvtnum(int fd)
67{
68 int ret;
69
70 ret = ioctl(fd, VT_OPENQRY, (int *)&TT.vt_num);
71 if (ret != 0 || TT.vt_num <= 0) perror_exit("can't find open VT");
72
73 return TT.vt_num;
74}
75
76void openvt_main(void)
77{
78 int fd, vt_fd, ret = 0;
79 struct vt_stat vstate;
80 pid_t pid;
81
82 if (!(toys.optflags & FLAG_c)) {
83
84 for (fd = 0; fd < 3; fd++)
85 if (!ioctl(fd, VT_GETSTATE, &vstate)) {
86 ret = xvtnum(fd);
87 break;
88 }
89
90
91 if (!ret) {
92 fd = xopen("/dev/console", O_RDONLY | O_NONBLOCK);
93 xioctl(fd, VT_GETSTATE, &vstate);
94 xvtnum(fd);
95 }
96 }
97
98 sprintf(toybuf, "/dev/tty%lu", TT.vt_num);
99 fd = open_console();
100 xioctl(fd, VT_GETSTATE, &vstate);
101
102 close(0);
103 vt_fd = xopen_stdio(toybuf, O_RDWR);
104 if (toys.optflags & FLAG_s) {
105 ioctl(vt_fd, VT_ACTIVATE, TT.vt_num);
106 ioctl(vt_fd, VT_WAITACTIVE, TT.vt_num);
107 }
108
109 close(1);
110 close(2);
111 dup2(vt_fd, 1);
112 dup2(vt_fd, 2);
113 while (vt_fd > 2)
114 close(vt_fd--);
115
116 pid = xfork();
117 if (!pid) {
118 setsid();
119 ioctl(vt_fd, TIOCSCTTY, 0);
120 xexec(toys.optargs);
121 }
122
123 if (toys.optflags & FLAG_w) {
124 while (-1 == waitpid(pid, NULL, 0) && errno == EINTR)
125 ;
126 if (toys.optflags & FLAG_s) {
127 ioctl(fd, VT_ACTIVATE, vstate.v_active);
128 ioctl(fd, VT_WAITACTIVE, vstate.v_active);
129
130 xioctl(fd, VT_DISALLOCATE, (void *)(ptrdiff_t)TT.vt_num);
131 }
132 }
133}
134
135void deallocvt_main(void)
136{
137 long vt_num = 0;
138 int fd;
139
140 if (*toys.optargs) vt_num = atolx_range(*toys.optargs, 1, 63);
141
142 if ((fd = open_console()) < 0) error_exit("can't open console");
143 xioctl(fd, VT_DISALLOCATE, (void *)vt_num);
144 if (CFG_TOYBOX_FREE) close(fd);
145}
146