xref: /third_party/toybox/toys/pending/openvt.c (revision 0f66f451)
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
7USE_OPENVT(NEWTOY(openvt, "c#<1>63sw", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
8USE_DEALLOCVT(NEWTOY(deallocvt, ">1", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NEEDROOT))
9
10config 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
25config 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
39GLOBALS(
40  long c;
41)
42
43int 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
57void 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
94void 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