// SPDX-License-Identifier: Apache-2.0 // // chvt N -- show virtual terminal N. // // The same name and the same argument as the Linux tool, because it does the // same thing and nobody should have to learn a second one. Alt+F1..F6 does // this from the keyboard; this does it from a script, and from a serial // console where there are no function keys to press. // // chvt report which terminal is active and which are in use // chvt 2 switch to /dev/tty2 #include "types.h" #include "user.h" #include "fcntl.h" #include "posix.h" // No printf in lib/, and this needs one string and two small numbers. static void puts(const char *s) { int n = 0; while (s[n]) n++; write(1, (void *)s, n); } static void putn(int v) { char b[12]; int i = 0; if (v < 0) { write(1, "-", 1); v = -v; } if (v == 0) { write(1, "0", 1); return; } while (v > 0) { b[i++] = '0' + (v % 10); v /= 10; } while (i-- > 0) write(1, &b[i], 1); } static int num(const char *s) { int v = 0; while (*s >= '0' && *s <= '9') v = v * 10 + (*s++ - '0'); return v; } int main(int argc, char *argv[]) { // /dev/console rather than fd 0: the caller may have redirected its input, // and the terminal being asked about is the machine's, not whichever one // this process happens to be reading from. int fd = open("/dev/console", O_RDWR); if (fd < 0) { puts("chvt: cannot open /dev/console\n"); exit(); } if (argc == 1) { struct vt_stat st; if (ioctl(fd, VT_GETSTATE, &st) < 0) { puts("chvt: VT_GETSTATE failed\n"); exit(); } puts("active: tty"); putn(st.v_active); puts("\nin use:"); for (int i = 1; i <= 16; i++) if (st.v_state & (1 << i)) { puts(" tty"); putn(i); } puts("\n"); exit(); } int n = num(argv[1]); if (n < 1) { puts("usage: chvt N\n"); exit(); } // The argument goes by value, not through a pointer -- Linux defines // VT_ACTIVATE that way and so does SchOS. Passing a pointer here would // switch to whatever the address happened to be. if (ioctl(fd, VT_ACTIVATE, (void *)(long)n) < 0) { puts("chvt: no terminal "); putn(n); puts("\n"); exit(); } exit(); }