1
2
3
4
5
6
7
8
9
10
11#include <linux/vt.h>
12#include "libbb.h"
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49static int not_vt_fd(int fd)
50{
51 struct vt_stat vtstat;
52 return ioctl(fd, VT_GETSTATE, &vtstat);
53}
54
55
56static int get_vt_fd(void)
57{
58 int fd;
59
60
61 for (fd = 0; fd < 3; fd++)
62 if (!not_vt_fd(fd))
63 return fd;
64 fd = open(DEV_CONSOLE, O_RDONLY | O_NONBLOCK);
65 if (fd >= 0 && !not_vt_fd(fd))
66 return fd;
67 bb_error_msg_and_die("can't find open VT");
68}
69
70static int find_free_vtno(void)
71{
72 int vtno;
73 int fd = get_vt_fd();
74
75 errno = 0;
76
77 if (ioctl(fd, VT_OPENQRY, &vtno) != 0 || vtno <= 0)
78 bb_perror_msg_and_die("can't find open VT");
79
80
81
82 return vtno;
83}
84
85
86
87
88
89static NOINLINE void vfork_child(char **argv)
90{
91 if (vfork() == 0) {
92
93
94 setsid();
95 ioctl(STDIN_FILENO, TIOCSCTTY, 0 );
96
97
98
99
100 BB_EXECVP_or_die(argv);
101 }
102}
103
104int openvt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
105int openvt_main(int argc UNUSED_PARAM, char **argv)
106{
107 char vtname[sizeof(VC_FORMAT) + sizeof(int)*3];
108 struct vt_stat vtstat;
109 char *str_c;
110 int vtno;
111 int flags;
112 enum {
113 OPT_c = (1 << 0),
114 OPT_w = (1 << 1),
115 OPT_s = (1 << 2),
116 OPT_l = (1 << 3),
117 OPT_f = (1 << 4),
118 OPT_v = (1 << 5),
119 };
120
121
122 flags = getopt32(argv, "+c:wslfv", &str_c);
123 argv += optind;
124
125 if (flags & OPT_c) {
126
127 vtno = xatou_range(str_c, 1, 63);
128 } else {
129 vtno = find_free_vtno();
130 }
131
132
133 sprintf(vtname, VC_FORMAT, vtno);
134
135 bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS | DAEMON_ONLY_SANITIZE, NULL);
136 close(STDIN_FILENO);
137
138 xopen(vtname, O_RDWR);
139 xioctl(STDIN_FILENO, VT_GETSTATE, &vtstat);
140
141 if (flags & OPT_s) {
142 console_make_active(STDIN_FILENO, vtno);
143 }
144
145 if (!argv[0]) {
146 argv--;
147 argv[0] = getenv("SHELL");
148 if (!argv[0])
149 argv[0] = (char *) DEFAULT_SHELL;
150
151 }
152
153 xdup2(STDIN_FILENO, STDOUT_FILENO);
154 xdup2(STDIN_FILENO, STDERR_FILENO);
155
156#ifdef BLOAT
157 {
158
159 const char *prog = argv[0];
160 if (flags & OPT_l)
161 argv[0] = xasprintf("-%s", argv[0]);
162 }
163#endif
164
165 vfork_child(argv);
166 if (flags & OPT_w) {
167
168 safe_waitpid(-1, NULL, 0);
169 if (flags & OPT_s) {
170 console_make_active(STDIN_FILENO, vtstat.v_active);
171
172
173
174 xioctl(STDIN_FILENO, VT_DISALLOCATE, (void*)(ptrdiff_t)vtno);
175 }
176 }
177 return EXIT_SUCCESS;
178}
179