fix: keyboard CTRL key support for CTRL+C/CTRL+Z in shell
Root cause: The PS/2 keyboard driver had no CTRL key tracking.
When CTRL was held and a letter pressed, the driver sent the
plain letter character (e.g., 'c') instead of the control
character (e.g., 0x03 for CTRL+C).
Fix: Added ctrl_held state tracking in hal/x86/keyboard.c for
Left CTRL (scancode 0x1D press / 0x9D release). When CTRL is
held and a letter key is pressed, emit (c & 0x1F) — the
standard control character encoding:
CTRL+C = 0x03, CTRL+Z = 0x1A, CTRL+D = 0x04, etc.
Shell read_line_edit() already handled these bytes correctly:
- 0x03 (CTRL+C): prints ^C, newline, cancels current line
- 0x1A (CTRL+Z): ignored at prompt (no foreground job)
- 0x04 (CTRL+D): EOF on empty line
During command execution, tty_restore() re-enables ISIG, so
the TTY kernel driver intercepts CTRL+C/CTRL+Z and sends
SIGINT/SIGTSTP to the foreground process group via TIOCSPGRP.