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