toybox/toys/other/openvt.c
<<
>>
Prefs
   1/* openvt.c - Run a program on a new VT
   2 *
   3 * Copyright 2008 David Anders <danders@amltd.com>
   4 * Copyright 2014 Vivek Kumar Bhagat <vivek.bhagat89@gmail.com>
   5 *
   6 * No Standard
   7
   8USE_OPENVT(NEWTOY(openvt, "^<1c#<1>63sw", TOYFLAG_BIN|TOYFLAG_NEEDROOT))
   9USE_CHVT(NEWTOY(chvt, "<1", TOYFLAG_USR|TOYFLAG_BIN))
  10USE_DEALLOCVT(NEWTOY(deallocvt, ">1", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_NEEDROOT))
  11
  12config OPENVT
  13  bool "openvt"
  14  default y
  15  help
  16    usage: openvt [-c NUM] [-sw] COMMAND...
  17
  18    Run COMMAND on a new virtual terminal.
  19
  20    -c NUM  Use VT NUM
  21    -s    Switch to the new VT
  22    -w    Wait for command to exit (with -s, deallocates VT on exit)
  23
  24config CHVT
  25  bool "chvt"
  26  default y
  27  help
  28    usage: chvt NUM
  29
  30    Change to virtual terminal number NUM. (This only works in text mode.)
  31
  32    Virtual terminals are the Linux VGA text mode (or framebuffer) displays,
  33    switched between via alt-F1, alt-F2, etc. Use ctrl-alt-F1 to switch
  34    from X11 to a virtual terminal, and alt-F6 (or F7, or F8) to get back.
  35
  36config DEALLOCVT
  37  bool "deallocvt"
  38  default y
  39  help
  40    usage: deallocvt [NUM]
  41
  42    Deallocate unused virtual terminals, either a specific /dev/ttyNUM, or all.
  43*/
  44
  45#define FOR_openvt
  46#include "toys.h"
  47#include <linux/vt.h>
  48#include <linux/kd.h>
  49
  50GLOBALS(
  51  long c;
  52)
  53
  54static int open_console(void)
  55{
  56  char arg = 0, *console_name[] = {"/dev/tty", "/dev/tty0", "/dev/console"};
  57  int i, fd;
  58
  59  for (i = 0; i < ARRAY_LEN(console_name); i++) {
  60    if (0>(fd = open(console_name[i], O_RDWR))) continue;
  61    if (!ioctl(fd, KDGKBTYPE, &arg)) return fd;
  62    close(fd);
  63  }
  64  for (fd = 0; fd < 3; fd++) if (!ioctl(fd, KDGKBTYPE, &arg)) return fd;
  65  error_exit("can't open console");
  66}
  67
  68static int activate(int fd, int cc)
  69{
  70  return ioctl(fd, VT_ACTIVATE, cc) || ioctl(fd, VT_WAITACTIVE, cc);
  71}
  72
  73void openvt_main(void)
  74{
  75  struct vt_stat vstate;
  76  int fd, cc = (int)TT.c;
  77  pid_t pid;
  78
  79  // find current console
  80  if (-1 == (ioctl(fd = open_console(), VT_GETSTATE, &vstate)) ||
  81      (!cc && 0>=(cc = xioctl(fd, VT_OPENQRY, &fd))))
  82    perror_exit("can't find open VT");
  83
  84  sprintf(toybuf, "/dev/tty%d", cc);
  85  if (!(pid = XVFORK())) {
  86    close(0);  //new vt becomes stdin
  87    dup2(dup2(xopen_stdio(toybuf, O_RDWR), 1), 2);
  88    if (FLAG(s)) activate(0, cc);
  89    setsid();
  90    ioctl(0, TIOCSCTTY, 0);
  91    if (fd>2) close(fd);
  92    xexec(toys.optargs);
  93  }
  94  if (FLAG(w)) {
  95    while (-1 == waitpid(pid, NULL, 0) && errno == EINTR) errno = 0;
  96    if (FLAG(s)) {
  97      activate(fd, vstate.v_active);
  98      dprintf(2, "%d\n", ioctl(fd, VT_DISALLOCATE, cc));
  99    }
 100  }
 101}
 102
 103void chvt_main(void)
 104{
 105  if (activate(open_console(), atoi(*toys.optargs)))
 106    perror_exit_raw(*toys.optargs);
 107}
 108
 109void deallocvt_main(void)
 110{
 111  int fd = open_console(), vt_num = 0; // 0 = all
 112
 113  if (*toys.optargs) vt_num = atolx_range(*toys.optargs, 1, 63);
 114  if (-1 == ioctl(fd, VT_DISALLOCATE, vt_num)) perror_exit("%d", vt_num);
 115}
 116