openvt.c 2.8 KB

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