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
65
66 fd = open(DEV_CONSOLE, O_NONBLOCK);
67 if (fd >= 0 && !not_vt_fd(fd))
68 return fd;
69 bb_error_msg_and_die("can't find open VT");
70}
71
72static int find_free_vtno(void)
73{
74 int vtno;
75 int fd = get_vt_fd();
76
77 errno = 0;
78
79 if (ioctl(fd, VT_OPENQRY, &vtno) != 0 || vtno <= 0)
80 bb_perror_msg_and_die("can't find open VT");
81
82
83
84 return vtno;
85}
86
87
88
89
90
91static NOINLINE void vfork_child(char **argv)
92{
93 if (vfork() == 0) {
94
95
96 setsid();
97 ioctl(STDIN_FILENO, TIOCSCTTY, 0 );
98
99
100
101
102 BB_EXECVP(argv[0], argv);
103 bb_perror_msg_and_die("exec %s", argv[0]);
104 }
105}
106
107int openvt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
108int openvt_main(int argc UNUSED_PARAM, char **argv)
109{
110 char vtname[sizeof(VC_FORMAT) + sizeof(int)*3];
111 struct vt_stat vtstat;
112 char *str_c;
113 int vtno;
114 int flags;
115 enum {
116 OPT_c = (1 << 0),
117 OPT_w = (1 << 1),
118 OPT_s = (1 << 2),
119 OPT_l = (1 << 3),
120 OPT_f = (1 << 4),
121 OPT_v = (1 << 5),
122 };
123
124
125 flags = getopt32(argv, "+c:wslfv", &str_c);
126 argv += optind;
127
128 if (flags & OPT_c) {
129
130 vtno = xatou_range(str_c, 1, 63);
131 } else {
132 vtno = find_free_vtno();
133 }
134
135
136 sprintf(vtname, VC_FORMAT, vtno);
137
138 bb_daemonize_or_rexec(DAEMON_CLOSE_EXTRA_FDS | DAEMON_ONLY_SANITIZE, NULL);
139 close(STDIN_FILENO);
140
141 xopen(vtname, O_RDWR);
142 xioctl(STDIN_FILENO, VT_GETSTATE, &vtstat);
143
144 if (flags & OPT_s) {
145 console_make_active(STDIN_FILENO, vtno);
146 }
147
148 if (!argv[0]) {
149 argv--;
150 argv[0] = getenv("SHELL");
151 if (!argv[0])
152 argv[0] = (char *) DEFAULT_SHELL;
153
154 }
155
156 xdup2(STDIN_FILENO, STDOUT_FILENO);
157 xdup2(STDIN_FILENO, STDERR_FILENO);
158
159#ifdef BLOAT
160 {
161
162 const char *prog = argv[0];
163 if (flags & OPT_l)
164 argv[0] = xasprintf("-%s", argv[0]);
165 }
166#endif
167
168 vfork_child(argv);
169 if (flags & OPT_w) {
170
171 safe_waitpid(-1, NULL, 0);
172 if (flags & OPT_s) {
173 console_make_active(STDIN_FILENO, vtstat.v_active);
174
175
176
177 xioctl(STDIN_FILENO, VT_DISALLOCATE, (void*)(ptrdiff_t)vtno);
178 }
179 }
180 return EXIT_SUCCESS;
181}
182