# Linux Kernel Module Cheat

#### 17.17.3. TTY

In order to play with TTYs, do this:

    printf '
    tty2::respawn:/sbin/getty -n -L -l /lkmc/loginroot.sh tty2 0 vt100
    tty3::respawn:-/bin/sh
    tty4::respawn:/sbin/getty 0 tty4
    tty63::respawn:-/bin/sh
    ::respawn:/sbin/getty -L ttyS0 0 vt100
    ::respawn:/sbin/getty -L ttyS1 0 vt100
    ::respawn:/sbin/getty -L ttyS2 0 vt100
    # Leave one serial empty.
    #::respawn:/sbin/getty -L ttyS3 0 vt100
    ' >> rootfs_overlay/etc/inittab
    ./build-buildroot
    ./run --graphic -- \
      -serial telnet::1235,server,nowait \
      -serial vc:800x600 \
      -serial telnet::1236,server,nowait \
    ;

and on a second shell:

    telnet localhost 1235

We don’t add more TTYs by default because it would spawn more processes, even if we use `askfirst` instead of `respawn`.

On the GUI, switch TTYs with:

- `Alt-Left` or `Alt-Right:` go to previous / next populated `/dev/ttyN` TTY. Skips over empty TTYs.

- `Alt-Fn`: go to the nth TTY. If it is not populated, don’t go there.

- `chvt <n>`: go to the n-th virtual TTY, even if it is empty: https://superuser.com/questions/33065/console-commands-to-change-virtual-ttys-in-linux-and-openbsd

You can also test this on most hosts such as Ubuntu 18.04, except that when in the GUI, you must use `Ctrl-Alt-Fx` to switch to another terminal.

Next, we also have the following shells running on the serial ports, hit enter to activate them:

- `/dev/ttyS0`: first shell that was used to run QEMU, corresponds to QEMU’s `-serial mon:stdio`.

  It would also work if we used `-serial stdio`, but:

  - `Ctrl-C` would kill QEMU instead of going to the guest

  - `Ctrl-A C` wouldn’t open the QEMU console there

  see also: https://stackoverflow.com/questions/49716931/how-to-run-qemu-with-nographic-and-monitor-but-still-be-able-to-send-ctrlc-to

- `/dev/ttyS1`: second shell running `telnet`

- `/dev/ttyS2`: go on the GUI and enter `Ctrl-Alt-2`, corresponds to QEMU’s `-serial vc`. Go back to the main console with `Ctrl-Alt-1`.

although we cannot change between terminals from there.

Each populated TTY contains a "shell":

- `-/bin/sh`: goes directly into an `sh` without a login prompt.

  The trailing dash `-` can be used on any command. It makes the command that follows take over the TTY, which is what we typically want for interactive shells: https://askubuntu.com/questions/902998/how-to-check-which-tty-am-i-using

  The `getty` executable however also does this operation and therefore dispenses the `-`.

- `/sbin/getty` asks for password, and then gives you an `sh`

  We can overcome the password prompt with the `-l /lkmc/loginroot.sh` technique explained at: https://askubuntu.com/questions/902998/how-to-check-which-tty-am-i-using but I don’t see any advantage over `-/bin/sh` currently.

Identify the current TTY with the command:

    tty

Bibliography:

- https://unix.stackexchange.com/questions/270272/how-to-get-the-tty-in-which-bash-is-running/270372

- https://unix.stackexchange.com/questions/187319/how-to-get-the-real-name-of-the-controlling-terminal

- https://unix.stackexchange.com/questions/77796/how-to-get-the-current-terminal-name

- https://askubuntu.com/questions/902998/how-to-check-which-tty-am-i-using

This outputs:

- `/dev/console` for the initial GUI terminal. But I think it is the same as `/dev/tty1`, because if I try to do

      tty1::respawn:-/bin/sh

  it makes the terminal go crazy, as if multiple processes are randomly eating up the characters.

- `/dev/ttyN` for the other graphic TTYs. Note that there are only 63 available ones, from `/dev/tty1` to `/dev/tty63` (`/dev/tty0` is the current one): https://superuser.com/questions/449781/why-is-there-so-many-linux-dev-tty. I think this is determined by:

      #define MAX_NR_CONSOLES 63

  in `linux/include/uapi/linux/vt.h`.

- `/dev/ttySN` for the text shells.

  These are Serial ports, see this to understand what those represent physically: https://unix.stackexchange.com/questions/307390/what-is-the-difference-between-ttys0-ttyusb0-and-ttyama0-in-linux/367882#367882

  There are only 4 serial ports, I think this is determined by QEMU. TODO check.

  See also: https://stackoverflow.com/questions/16706423/two-instances-of-busybox-on-separate-serial-lines-ttysn

Get the TTY in bulk for all processes:

    ./psa.sh

Source: rootfs_overlay/lkmc/psa.sh.

The TTY appears under the `TT` section, which is enabled by `-o tty`. This shows the TTY device number, e.g.:

    4,1

and we can then confirm it with:

    ls -l /dev/tty1

Next try:

    insmod kthread.ko

and switch between virtual terminals, to understand that the dmesg goes to whatever current virtual terminal you are on, but not the others, and not to the serial terminals.

Bibliography:

- https://serverfault.com/questions/119736/how-to-enable-multiple-virtual-consoles-on-linux

- https://github.com/mirror/busybox/blob/1_28_3/examples/inittab#L60

- http://web.archive.org/web/20180117124612/http://nairobi-embedded.org/qemu_serial_port_system_console.html

- Start a getty from outside of init

- console kernel boot parameter