
Terminal Docs
- 28 installs
- 35 repo stars
- Updated April 28, 2026
- mwguerra/claude-code-plugins
Helps with ai & agent building tasks.
About
terminal-docs is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- terminal-docs
- AI & Agent Building
- AI-coding skill
Terminal Docs by the numbers
- 28 all-time installs (skills.sh)
- Ranked #9,505 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/mwguerra/claude-code-plugins --skill terminal-docsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 28 |
|---|---|
| repo stars | ★ 35 |
| Last updated | April 28, 2026 |
| Repository | mwguerra/claude-code-plugins ↗ |
What it does
Helps with ai & agent building tasks.
Files
Terminal Documentation Reference Skill
Overview
This skill provides access to comprehensive terminal and shell systems documentation. Use this skill to look up exact configurations, code patterns, and best practices for terminal-related development.
Documentation Location
All documentation is stored in: /home/mwguerra/projects/mwguerra/claude-code-plugins/terminal-specialist/skills/terminal-docs/references/
Directory Structure
references/
├── 01-fundamentals.md # TTY/PTY concepts, terminal stack, device files
├── 02-streams.md # stdin, stdout, stderr, buffering behavior
├── 03-exit-codes.md # Exit status, POSIX codes, signal exits
├── 04-shells.md # Shell types, startup files, options
├── 05-dimensions.md # Terminal size, SIGWINCH, resize handling
├── 06-modes.md # Canonical/raw mode, termios flags
├── 07-job-control.md # Sessions, process groups, background jobs
├── 08-environment.md # TERM, PATH, locale, prompt variables
├── 09-signals.md # Signal handling, keyboard signals
├── 10-escape-sequences.md # ANSI codes, colors, cursor control
├── 11-redirection.md # Pipes, file descriptors, here docs
├── 12-windows.md # Windows console, ConPTY, PowerShell
├── 13-cross-platform.md # Portable patterns, platform differences
└── 14-advanced.md # tmux, screen, recording, graphicsUsage
When to Use This Skill
1. Before implementing terminal-related functionality 2. When debugging I/O or stream issues 3. To verify correct escape sequence syntax 4. To understand terminal mode behavior 5. For signal handling patterns 6. For cross-platform compatibility guidance
Search Workflow
1. Identify Topic: Determine what documentation is needed 2. Navigate to File: Go to relevant documentation file 3. Read Documentation: Extract exact patterns 4. Apply Knowledge: Use in implementation
Common Lookups
| Topic | File |
|---|---|
| Terminal architecture | 01-fundamentals.md |
| Stream buffering | 02-streams.md |
| Exit codes | 03-exit-codes.md |
| Shell configuration | 04-shells.md |
| Terminal size | 05-dimensions.md |
| Raw mode | 06-modes.md |
| Job control | 07-job-control.md |
| Environment variables | 08-environment.md |
| Signal handling | 09-signals.md |
| ANSI escape codes | 10-escape-sequences.md |
| Pipes and redirection | 11-redirection.md |
| Windows console | 12-windows.md |
| Cross-platform | 13-cross-platform.md |
| Multiplexers | 14-advanced.md |
Documentation Reading Pattern
When reading documentation:
1. Find the right file: Match topic to documentation file 2. Read the overview: Understand the concept 3. Extract code examples: Copy exact patterns 4. Note platform specifics: Consider Unix/Windows differences 5. Check best practices: Apply safety and portability tips
Example Usage
Looking up ANSI Color Codes
1. Navigate to 10-escape-sequences.md 2. Find Colors section 3. Extract:
- 4-bit color codes (30-37, 40-47)
- 256-color format
- True color format
- tput commands
Looking up Signal Handling
1. Navigate to 09-signals.md 2. Find relevant section (Bash, C, Python) 3. Extract:
- Signal handler setup
- Signal-safe patterns
- Cleanup handlers
Looking up Cross-Platform Input
1. Navigate to 13-cross-platform.md 2. Find Key Input section 3. Extract:
- Unix termios pattern
- Windows msvcrt pattern
- Platform detection code
Output
After reading documentation, provide:
1. Exact code pattern from docs 2. Platform considerations 3. Best practices noted 4. Safety/security notes 5. Alternative approaches if applicable
Terminal Fundamentals
1. What is a Terminal?
A terminal (or terminal emulator) is a program that provides a text-based interface for interacting with a computer's operating system through a shell. Historically, terminals were physical hardware devices (teletypewriters/TTYs), but modern terminals are software emulations.
2. Key Terminology
| Term | Definition |
|---|---|
| TTY | Teletypewriter - the original hardware terminals; now refers to terminal devices in Unix |
| PTY | Pseudo-terminal - a software emulation of a terminal device |
| Console | The primary terminal connected directly to the system (physical or virtual) |
| Terminal Emulator | Software that emulates a hardware terminal (e.g., xterm, GNOME Terminal, iTerm2, Windows Terminal) |
| Shell | Command interpreter that runs inside a terminal (e.g., bash, zsh, PowerShell) |
| Command Line | The text interface where commands are entered |
3. The Terminal Stack
┌─────────────────────────────────────────┐
│ User Input/Output │
├─────────────────────────────────────────┤
│ Terminal Emulator │
│ (xterm, Windows Terminal, iTerm2) │
├─────────────────────────────────────────┤
│ PTY (Pseudo-Terminal) │
│ Master ←──→ Slave │
├─────────────────────────────────────────┤
│ Shell │
│ (bash, zsh, PowerShell, cmd) │
├─────────────────────────────────────────┤
│ Operating System │
│ (Kernel, System Calls) │
└─────────────────────────────────────────┘4. PTY Architecture (Unix/Linux)
A pseudo-terminal consists of two parts:
- PTY Master: Held by the terminal emulator; receives input and sends output
- PTY Slave: Attached to the shell/process; appears as a real terminal device
Terminal Emulator ←→ PTY Master ←→ PTY Slave ←→ Shell ←→ Child Processes
↑ ↓
User sees Commands run
output and produce
output5. Device Files (Unix/Linux)
| Path | Description |
|---|---|
/dev/tty | Current controlling terminal |
/dev/tty[0-63] | Virtual console devices |
/dev/pts/* | Pseudo-terminal slave devices |
/dev/ptmx | PTY master multiplexor |
/dev/console | System console |
/dev/null | Null device (discards all input) |
/dev/zero | Produces infinite null bytes |
/dev/stdin | Symlink to fd 0 |
/dev/stdout | Symlink to fd 1 |
/dev/stderr | Symlink to fd 2 |
6. Terminal Emulators
Common Terminal Emulators
| Platform | Terminal Emulators |
|---|---|
| Linux | GNOME Terminal, Konsole, xterm, Alacritty, Kitty, Terminator |
| macOS | Terminal.app, iTerm2, Alacritty, Kitty, Hyper |
| Windows | Windows Terminal, ConHost, ConEmu, Cmder, Hyper |
| Cross-platform | Alacritty, Kitty, Hyper, Warp |
Terminal Capabilities
Terminals vary in their feature support:
| Feature | Description |
|---|---|
| True color (24-bit) | 16 million colors |
| 256 colors | Extended color palette |
| Unicode | Full character set support |
| Ligatures | Font ligature rendering |
| GPU acceleration | Hardware-accelerated rendering |
| Sixel graphics | Inline image display |
| OSC 52 | Clipboard integration |
7. Building a Terminal Emulator
Understanding how to build a terminal emulator reveals the full complexity of terminal systems.
Core Architecture
┌────────────────────────────────────────────────────────────────────┐
│ Terminal Emulator Application │
├────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌───────────┐ │
│ │ Input │ │ Parser │ │ Terminal │ │ Renderer │ │
│ │ Handler │──▶│ (VT/ANSI) │──▶│ State │──▶│ (Grid) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └───────────┘ │
│ ▲ │ │
│ │ ▼ │
│ ┌─────────────┐ ┌───────────┐ │
│ │ Keyboard │ │ Display │ │
│ │ Events │ │ (GPU/SW) │ │
│ └─────────────┘ └───────────┘ │
│ │
├────────────────────────────────────────────────────────────────────┤
│ PTY Interface │
│ (read/write to child process) │
└────────────────────────────────────────────────────────────────────┘Essential Components
1. PTY Management
The terminal emulator must create and manage a pseudo-terminal pair:
// Unix/Linux: Create PTY pair
#include <pty.h>
#include <utmp.h>
int master_fd, slave_fd;
char slave_name[256];
// Create PTY pair
if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) == -1) {
perror("openpty");
exit(1);
}
// Fork child process
pid_t pid = fork();
if (pid == 0) {
// Child: becomes the shell
close(master_fd);
setsid(); // Create new session
ioctl(slave_fd, TIOCSCTTY, 0); // Set controlling terminal
// Redirect stdio to PTY slave
dup2(slave_fd, STDIN_FILENO);
dup2(slave_fd, STDOUT_FILENO);
dup2(slave_fd, STDERR_FILENO);
close(slave_fd);
// Execute shell
execlp("/bin/bash", "bash", NULL);
} else {
// Parent: terminal emulator
close(slave_fd);
// master_fd is used for all I/O with child
}2. Terminal State (Screen Buffer)
The terminal maintains a grid of cells representing the screen:
typedef struct {
uint32_t codepoint; // Unicode character
uint32_t fg_color; // Foreground color (RGB or indexed)
uint32_t bg_color; // Background color
uint8_t attributes; // Bold, italic, underline, etc.
uint8_t width; // Character width (1 or 2 for wide chars)
} Cell;
typedef struct {
Cell *cells; // Grid of cells (rows * cols)
int rows;
int cols;
int cursor_row;
int cursor_col;
int scroll_top; // Scroll region top
int scroll_bottom; // Scroll region bottom
// Saved cursor state (for ESC 7 / ESC 8)
int saved_cursor_row;
int saved_cursor_col;
// Current attributes for new characters
uint32_t current_fg;
uint32_t current_bg;
uint8_t current_attrs;
// Modes
bool cursor_visible;
bool origin_mode; // DECOM
bool autowrap; // DECAWM
bool insert_mode;
bool application_cursor; // DECCKM
bool bracketed_paste;
bool mouse_tracking;
bool alternate_screen; // Alternate screen buffer
// Alternate screen buffer
Cell *alt_cells;
int alt_cursor_row;
int alt_cursor_col;
} TerminalState;3. VT/ANSI Parser
A state machine that parses escape sequences from the PTY output:
typedef enum {
STATE_GROUND, // Normal character processing
STATE_ESCAPE, // After ESC
STATE_CSI_ENTRY, // After ESC [
STATE_CSI_PARAM, // Reading CSI parameters
STATE_CSI_INTERMEDIATE, // CSI intermediate bytes
STATE_OSC_STRING, // Operating System Command
STATE_DCS_ENTRY, // Device Control String
// ... more states
} ParserState;
typedef struct {
ParserState state;
int params[16]; // Numeric parameters
int param_count;
char intermediates[4]; // Intermediate characters
int intermediate_count;
char osc_string[4096]; // OSC string buffer
int osc_len;
} Parser;
void parse_byte(Parser *p, TerminalState *term, uint8_t byte) {
switch (p->state) {
case STATE_GROUND:
if (byte == 0x1B) { // ESC
p->state = STATE_ESCAPE;
} else if (byte >= 0x20 && byte < 0x7F) {
// Printable character
put_char(term, byte);
} else if (byte < 0x20) {
// Control character (CR, LF, BS, TAB, etc.)
handle_control_char(term, byte);
}
break;
case STATE_ESCAPE:
if (byte == '[') {
p->state = STATE_CSI_ENTRY;
p->param_count = 0;
} else if (byte == ']') {
p->state = STATE_OSC_STRING;
p->osc_len = 0;
} else if (byte == '7') {
save_cursor(term);
p->state = STATE_GROUND;
} else if (byte == '8') {
restore_cursor(term);
p->state = STATE_GROUND;
}
// ... handle other escape sequences
break;
case STATE_CSI_PARAM:
if (byte >= '0' && byte <= '9') {
// Accumulate parameter digit
p->params[p->param_count] = p->params[p->param_count] * 10 + (byte - '0');
} else if (byte == ';') {
// Next parameter
p->param_count++;
} else if (byte >= 0x40 && byte <= 0x7E) {
// Final byte - execute CSI sequence
execute_csi(term, p, byte);
p->state = STATE_GROUND;
}
break;
// ... other states
}
}
void execute_csi(TerminalState *term, Parser *p, char final) {
int n = p->params[0] ? p->params[0] : 1; // Default to 1
switch (final) {
case 'A': cursor_up(term, n); break;
case 'B': cursor_down(term, n); break;
case 'C': cursor_forward(term, n); break;
case 'D': cursor_backward(term, n); break;
case 'H': cursor_position(term, p->params[0], p->params[1]); break;
case 'J': erase_in_display(term, p->params[0]); break;
case 'K': erase_in_line(term, p->params[0]); break;
case 'm': set_graphics_rendition(term, p); break; // Colors/attributes
// ... many more
}
}4. Input Handling
Convert keyboard events to escape sequences for the PTY:
void handle_key(int master_fd, KeyEvent *event) {
char buf[32];
int len = 0;
if (event->key == KEY_ENTER) {
buf[0] = '\r'; // Carriage return
len = 1;
} else if (event->key == KEY_BACKSPACE) {
buf[0] = 0x7F; // DEL or 0x08 (BS) depending on mode
len = 1;
} else if (event->key == KEY_UP) {
// Application mode vs normal mode
if (application_cursor_mode) {
len = sprintf(buf, "\x1bOA");
} else {
len = sprintf(buf, "\x1b[A");
}
} else if (event->key == KEY_DOWN) {
len = sprintf(buf, application_cursor_mode ? "\x1bOB" : "\x1b[B");
} else if (event->key == KEY_RIGHT) {
len = sprintf(buf, application_cursor_mode ? "\x1bOC" : "\x1b[C");
} else if (event->key == KEY_LEFT) {
len = sprintf(buf, application_cursor_mode ? "\x1bOD" : "\x1b[D");
} else if (event->key == KEY_HOME) {
len = sprintf(buf, "\x1b[H");
} else if (event->key == KEY_END) {
len = sprintf(buf, "\x1b[F");
} else if (event->key == KEY_F1) {
len = sprintf(buf, "\x1bOP"); // Or \x1b[11~ depending on terminal
} else if (event->ctrl && event->key >= 'a' && event->key <= 'z') {
// Ctrl+letter produces control character
buf[0] = event->key - 'a' + 1; // Ctrl+A = 0x01, etc.
len = 1;
} else if (event->unicode) {
// Regular character - encode as UTF-8
len = encode_utf8(buf, event->unicode);
}
// Handle bracketed paste mode
if (event->is_paste && bracketed_paste_mode) {
write(master_fd, "\x1b[200~", 6);
write(master_fd, event->paste_text, event->paste_len);
write(master_fd, "\x1b[201~", 6);
} else if (len > 0) {
write(master_fd, buf, len);
}
}5. Rendering
Draw the terminal state to the screen:
void render_terminal(TerminalState *term, Renderer *r) {
for (int row = 0; row < term->rows; row++) {
for (int col = 0; col < term->cols; col++) {
Cell *cell = &term->cells[row * term->cols + col];
// Set colors
set_foreground(r, cell->fg_color);
set_background(r, cell->bg_color);
// Apply attributes
if (cell->attributes & ATTR_BOLD) set_bold(r, true);
if (cell->attributes & ATTR_ITALIC) set_italic(r, true);
if (cell->attributes & ATTR_UNDERLINE) set_underline(r, true);
if (cell->attributes & ATTR_REVERSE) {
// Swap fg/bg
swap_colors(r);
}
// Calculate pixel position
int x = col * font_cell_width;
int y = row * font_cell_height;
// Draw background
fill_rect(r, x, y, font_cell_width, font_cell_height);
// Draw character (handle wide characters)
if (cell->codepoint != 0 && cell->codepoint != ' ') {
draw_glyph(r, x, y, cell->codepoint);
}
// Skip next cell if wide character
if (cell->width == 2) col++;
}
}
// Draw cursor
if (term->cursor_visible) {
int x = term->cursor_col * font_cell_width;
int y = term->cursor_row * font_cell_height;
draw_cursor(r, x, y, cursor_style);
}
}Main Event Loop
int main() {
// Initialize window/graphics
Window *window = create_window(80 * font_width, 24 * font_height);
// Create PTY and spawn shell
int master_fd = create_pty_and_spawn_shell();
// Initialize terminal state
TerminalState term = {0};
term.rows = 24;
term.cols = 80;
term.cells = calloc(term.rows * term.cols, sizeof(Cell));
// Initialize parser
Parser parser = {0};
// Main loop
while (running) {
// Handle window/input events
Event event;
while (poll_event(&event)) {
if (event.type == EVENT_KEY) {
handle_key(master_fd, &event.key);
} else if (event.type == EVENT_RESIZE) {
// Update terminal size
term.rows = event.resize.height / font_height;
term.cols = event.resize.width / font_width;
resize_cells(&term);
// Notify PTY of new size
struct winsize ws = {term.rows, term.cols, 0, 0};
ioctl(master_fd, TIOCSWINSZ, &ws);
} else if (event.type == EVENT_CLOSE) {
running = false;
}
}
// Read output from PTY
char buf[4096];
ssize_t n = read(master_fd, buf, sizeof(buf));
if (n > 0) {
for (int i = 0; i < n; i++) {
parse_byte(&parser, &term, buf[i]);
}
}
// Render
render_terminal(&term, renderer);
present(window);
}
return 0;
}Key Challenges in Building a Terminal Emulator
| Challenge | Description |
|---|---|
| Escape Sequence Parsing | Hundreds of sequences to support (VT100, VT220, xterm, etc.) |
| Unicode & Wide Characters | Handle multi-byte UTF-8, combining characters, emoji, CJK |
| Performance | Efficient rendering for large scrollback, fast output |
| Correctness | Match behavior of reference terminals (xterm, VT100) |
| Font Rendering | Monospace alignment, ligatures, fallback fonts |
| Selection & Clipboard | Mouse selection, copy/paste integration |
| Scrollback Buffer | Efficient storage for thousands of lines |
| Sixel/Graphics | Inline image protocols |
| OSC Sequences | Hyperlinks, notifications, clipboard |
Required Knowledge Areas
1. Operating Systems
- Process creation (fork/exec)
- PTY/TTY subsystem
- Signal handling
- File descriptor I/O
2. Text Processing
- Unicode (UTF-8, code points, grapheme clusters)
- Character width (wcwidth)
- Bidirectional text (optional)
3. VT/ANSI Standards
- Control characters
- Escape sequences (CSI, OSC, DCS)
- Terminal modes
- Character attributes
4. Graphics
- 2D rendering (software or GPU)
- Font rasterization
- Color management
5. Event Handling
- Keyboard input mapping
- Mouse events
- Window management
Reference Implementations
| Terminal | Language | Notes |
|---|---|---|
| xterm | C | Reference implementation, most complete |
| Alacritty | Rust | GPU-accelerated, modern |
| Kitty | C/Python | GPU-accelerated, extensible |
| st | C | Simple, minimal (~2000 lines) |
| VTE | C | Library used by GNOME Terminal |
| Windows Terminal | C++ | Modern Windows terminal |
| mintty | C | Cygwin/MSYS2 terminal |
Testing Your Terminal
# Test basic functionality
vttest # Comprehensive VT compatibility test
tput colors # Check color support
echo -e "\e[31mRed\e[0m" # Basic color test
# Test Unicode
echo "Hello 世界 🎉"
printf '\u2603' # Snowman
# Test cursor movement
tput cup 10 20; echo "Here"
# Test alternate screen
tput smcup; sleep 2; tput rmcupStandard Streams: stdin, stdout, stderr
1. Overview
Every process in Unix/Linux/Windows has three standard streams automatically opened:
| Stream | File Descriptor | C Constant | Purpose |
|---|---|---|---|
| stdin | 0 | STDIN_FILENO | Standard input - where the process reads input |
| stdout | 1 | STDOUT_FILENO | Standard output - where the process writes normal output |
| stderr | 2 | STDERR_FILENO | Standard error - where the process writes error/diagnostic messages |
2. File Descriptors
File descriptors are non-negative integers that identify open files/streams in a process.
// C example
#include <unistd.h>
// These are always available:
// 0 = stdin
// 1 = stdout
// 2 = stderr
write(1, "Hello stdout\n", 13); // Write to stdout
write(2, "Hello stderr\n", 13); // Write to stderr
char buf[100];
read(0, buf, 100); // Read from stdin3. Buffering Behavior
Streams have different default buffering modes:
| Stream | Default Buffering | Description |
|---|---|---|
| stdin | Line-buffered (terminal) / Fully buffered (file) | Input is processed line by line or in blocks |
| stdout | Line-buffered (terminal) / Fully buffered (file) | Output is flushed on newline (terminal) or when buffer fills |
| stderr | Unbuffered | Output is written immediately |
Buffering Modes
| Mode | Description | Typical Use |
|---|---|---|
| Unbuffered | I/O happens immediately | stderr, critical output |
| Line-buffered | Buffer flushed on newline | Interactive terminal stdout |
| Fully-buffered | Buffer flushed when full (typically 4KB-64KB) | File I/O, pipes |
Controlling Buffering (C)
#include <stdio.h>
// Disable buffering entirely
setvbuf(stdout, NULL, _IONBF, 0);
// Line buffering
setvbuf(stdout, NULL, _IOLBF, 0);
// Full buffering with custom buffer
char buffer[8192];
setvbuf(stdout, buffer, _IOFBF, sizeof(buffer));
// Force flush
fflush(stdout);Controlling Buffering (Shell)
# Run command with unbuffered output
stdbuf -o0 command
# Line-buffered output
stdbuf -oL command
# Using unbuffer (from expect package)
unbuffer command
# Python unbuffered mode
python -u script.py
PYTHONUNBUFFERED=1 python script.py4. Checking if Connected to Terminal
Unix/Linux (C)
#include <unistd.h>
if (isatty(STDIN_FILENO)) {
printf("stdin is a terminal\n");
}
if (isatty(STDOUT_FILENO)) {
printf("stdout is a terminal\n");
}Bash
if [ -t 0 ]; then
echo "stdin is a terminal"
fi
if [ -t 1 ]; then
echo "stdout is a terminal"
fiPython
import sys
import os
print(f"stdin is TTY: {sys.stdin.isatty()}")
print(f"stdout is TTY: {sys.stdout.isatty()}")
print(f"stderr is TTY: {sys.stderr.isatty()}")
# Alternative using os module
print(f"stdin is TTY: {os.isatty(0)}")Node.js
process.stdin.isTTY // true if stdin is a terminal
process.stdout.isTTY // true if stdout is a terminal
process.stderr.isTTY // true if stderr is a terminal5. Stream Inheritance
When a process forks:
- Child inherits all open file descriptors
- File descriptors point to same underlying file descriptions
- Changes to file offset affect both processes
Parent Process Child Process (after fork)
┌─────────────────┐ ┌─────────────────┐
│ fd 0 → stdin │──────────────│ fd 0 → stdin │
│ fd 1 → stdout │──────────────│ fd 1 → stdout │
│ fd 2 → stderr │──────────────│ fd 2 → stderr │
│ fd 3 → file.txt │──────────────│ fd 3 → file.txt │
└─────────────────┘ └─────────────────┘
│ │
└────────────┬───────────────────┘
▼
File Description
(shared state)6. Redirecting Streams Programmatically
C
#include <unistd.h>
#include <fcntl.h>
// Redirect stdout to file
int fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
dup2(fd, STDOUT_FILENO);
close(fd);
// Redirect stderr to stdout
dup2(STDOUT_FILENO, STDERR_FILENO);Python
import sys
# Redirect stdout
sys.stdout = open('output.txt', 'w')
# Redirect stderr to stdout
sys.stderr = sys.stdout
# Restore
sys.stdout = sys.__stdout__
sys.stderr = sys.__stderr__Exit Codes and Process Termination
1. Exit Code Basics
An exit code (or exit status, return code) is an integer value returned by a process when it terminates. This value indicates success or failure to the parent process.
| Platform | Range | Success Value |
|---|---|---|
| Unix/Linux | 0-255 | 0 |
| Windows | 0-4294967295 (32-bit) | 0 |
2. Standard Exit Codes (Unix/Linux)
POSIX/BSD Standard Codes
| Code | Name | Meaning |
|---|---|---|
| 0 | EXIT_SUCCESS | Success |
| 1 | EXIT_FAILURE | General errors |
| 2 | Misuse of shell command | |
| 64 | EX_USAGE | Command line usage error |
| 65 | EX_DATAERR | Data format error |
| 66 | EX_NOINPUT | Cannot open input |
| 67 | EX_NOUSER | User doesn't exist |
| 68 | EX_NOHOST | Host doesn't exist |
| 69 | EX_UNAVAILABLE | Service unavailable |
| 70 | EX_SOFTWARE | Internal software error |
| 71 | EX_OSERR | System error |
| 72 | EX_OSFILE | Critical OS file missing |
| 73 | EX_CANTCREAT | Can't create output file |
| 74 | EX_IOERR | I/O error |
| 75 | EX_TEMPFAIL | Temporary failure |
| 76 | EX_PROTOCOL | Protocol error |
| 77 | EX_NOPERM | Permission denied |
| 78 | EX_CONFIG | Configuration error |
| 126 | Command not executable | |
| 127 | Command not found | |
| 128+N | Killed by signal N | |
| 130 | Killed by Ctrl+C (SIGINT) | |
| 137 | Killed by SIGKILL (128+9) | |
| 143 | Killed by SIGTERM (128+15) |
3. Accessing Exit Codes
Bash
# $? contains exit code of last command
command
echo "Exit code: $?"
# Using in conditionals
if command; then
echo "Success"
else
echo "Failed with code: $?"
fi
# PIPESTATUS array for pipeline exit codes
cmd1 | cmd2 | cmd3
echo "Exit codes: ${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]}"
# Exit with specific code
exit 0 # Success
exit 1 # FailureZsh
# Similar to bash but uses pipestatus (lowercase)
cmd1 | cmd2 | cmd3
echo "Exit codes: ${pipestatus[@]}"PowerShell
# $LASTEXITCODE for native commands
cmd /c exit 42
$LASTEXITCODE # Returns 42
# $? for PowerShell commands (boolean)
Get-Process
$? # Returns True or False
# Exit with code
exit 0cmd.exe
:: %ERRORLEVEL% contains exit code
command
echo Exit code: %ERRORLEVEL%
:: Conditional execution
command && echo Success || echo Failed
:: Exit with code
exit /b 0C
#include <stdlib.h>
#include <sys/wait.h>
int main() {
// Exit with success
exit(EXIT_SUCCESS); // or exit(0);
// Exit with failure
exit(EXIT_FAILURE); // or exit(1);
// From child process
pid_t pid = fork();
if (pid == 0) {
exit(42); // Child exits with 42
}
// Parent waits and gets exit code
int status;
wait(&status);
if (WIFEXITED(status)) {
int exit_code = WEXITSTATUS(status);
printf("Child exited with: %d\n", exit_code);
}
if (WIFSIGNALED(status)) {
int signal = WTERMSIG(status);
printf("Child killed by signal: %d\n", signal);
}
}Python
import sys
import subprocess
# Exit with code
sys.exit(0) # Success
sys.exit(1) # Failure
sys.exit("Error message") # Prints to stderr, exits with 1
# Get exit code from subprocess
result = subprocess.run(['ls', '-la'])
print(f"Exit code: {result.returncode}")
# With check=True, raises CalledProcessError on non-zero exit
try:
subprocess.run(['false'], check=True)
except subprocess.CalledProcessError as e:
print(f"Command failed with exit code: {e.returncode}")Node.js
// Exit with code
process.exit(0); // Success
process.exit(1); // Failure
// Get exit code from child process
const { spawn } = require('child_process');
const child = spawn('ls', ['-la']);
child.on('close', (code) => {
console.log(`Exit code: ${code}`);
});4. Exit Code Truncation
Exit codes are limited to 8 bits (0-255) in Unix/Linux:
exit(256); // Becomes 0 (256 % 256)
exit(257); // Becomes 1 (257 % 256)
exit(-1); // Becomes 255 (unsigned interpretation)5. Process Termination Methods
| Method | Description | Exit Code |
|---|---|---|
exit(n) | Normal termination | n |
_exit(n) | Immediate termination (no cleanup) | n |
return n | From main() | n |
| Signal | Killed by signal | 128 + signal number |
abort() | Abnormal termination (SIGABRT) | 128 + 6 = 134 |
6. Common Signal Exit Codes
| Signal | Number | Exit Code (128+N) |
|---|---|---|
| SIGHUP | 1 | 129 |
| SIGINT | 2 | 130 |
| SIGQUIT | 3 | 131 |
| SIGKILL | 9 | 137 |
| SIGTERM | 15 | 143 |
| SIGPIPE | 13 | 141 |
Shells
1. Shell Overview
A shell is a command interpreter that:
- Reads commands from stdin or scripts
- Parses and interprets commands
- Executes programs and built-in commands
- Manages job control
- Provides scripting capabilities
2. Common Unix/Linux Shells
| Shell | Path | Description |
|---|---|---|
| sh | /bin/sh | Bourne shell - POSIX standard |
| bash | /bin/bash | Bourne Again Shell - most common Linux default |
| zsh | /bin/zsh | Z shell - macOS default, highly customizable |
| fish | /usr/bin/fish | Friendly Interactive Shell - user-friendly |
| dash | /bin/dash | Debian Almquist Shell - fast, minimal |
| ksh | /bin/ksh | Korn shell - advanced features |
| tcsh | /bin/tcsh | Enhanced C shell |
3. Windows Shells
| Shell | Description |
|---|---|
| cmd.exe | Classic Windows command interpreter |
| PowerShell | Object-oriented shell with .NET integration |
| PowerShell Core | Cross-platform version of PowerShell |
| WSL Bash | Linux shells via Windows Subsystem for Linux |
4. Shell Startup Files
Bash
Login Shell Non-Login Interactive Shell
│ │
▼ ▼
/etc/profile ~/.bashrc
│
▼
~/.bash_profile
(or ~/.bash_login
or ~/.profile)
│
▼
~/.bashrc (if sourced)| File | When Read | Purpose |
|---|---|---|
/etc/profile | Login shells | System-wide settings |
~/.bash_profile | Login shells | User login settings |
~/.bashrc | Non-login interactive | User interactive settings |
~/.bash_logout | Login shell exit | Cleanup tasks |
Zsh
| File | When Read |
|---|---|
/etc/zshenv | Always |
~/.zshenv | Always |
/etc/zprofile | Login shells |
~/.zprofile | Login shells |
/etc/zshrc | Interactive shells |
~/.zshrc | Interactive shells |
/etc/zlogin | Login shells |
~/.zlogin | Login shells |
~/.zlogout | Login shell exit |
Fish
| File | When Read |
|---|---|
~/.config/fish/config.fish | Every fish session |
~/.config/fish/conf.d/*.fish | Every fish session |
~/.config/fish/functions/*.fish | On demand (autoloaded) |
5. Shell Types
# Check if login shell
shopt -q login_shell && echo "Login shell" || echo "Non-login shell" # Bash
# Check if interactive
[[ $- == *i* ]] && echo "Interactive" || echo "Non-interactive"
# Force login shell
bash -l
bash --login
# Force non-interactive
bash -c "command"| Type | Description |
|---|---|
| Login shell | First shell after login (ssh, console login) |
| Non-login | Subshells, new terminal windows |
| Interactive | Attached to terminal, accepts user input |
| Non-interactive | Running scripts, no user interaction |
6. Shell Built-ins vs External Commands
Built-in commands are part of the shell itself:
# List bash built-ins
enable -a
# Check if command is built-in
type cd # cd is a shell builtin
type ls # ls is /bin/ls
# Common built-ins
cd, echo, pwd, export, alias, source, exit, read, test, [, [[Why Built-ins Matter
- No process fork required (faster)
- Can modify shell state (cd, export)
- Behavior may differ from external commands
7. Shell Options
Bash Options
# Set options
set -e # Exit on error
set -u # Error on undefined variables
set -x # Print commands before execution
set -o pipefail # Pipeline fails if any command fails
# Combined
set -euo pipefail
# Unset options
set +e
# List all options
set -o
# Shopt options (Bash specific)
shopt -s globstar # Enable ** glob
shopt -s nullglob # Glob with no matches returns empty
shopt -u dotglob # Disable matching hidden filesCommon Set Options
| Option | Description |
|---|---|
-e / errexit | Exit on non-zero status |
-u / nounset | Error on undefined variables |
-x / xtrace | Print commands |
-v / verbose | Print shell input |
-n / noexec | Check syntax only |
-f / noglob | Disable filename expansion |
-o pipefail | Pipeline return status |
8. PowerShell Specifics
# Execution Policy
Get-ExecutionPolicy
Set-ExecutionPolicy RemoteSigned
# Profiles
$PROFILE # Current user, current host
$PROFILE.CurrentUserAllHosts # Current user, all hosts
$PROFILE.AllUsersCurrentHost # All users, current host
$PROFILE.AllUsersAllHosts # All users, all hosts
# Error handling
$ErrorActionPreference = "Stop" # Similar to set -e
$Error # Array of recent errors
# Exit codes
$LASTEXITCODE # Exit code from native commands
$? # Success status of last command (boolean)9. Shell Variables
Special Variables (Bash)
| Variable | Description |
|---|---|
$0 | Script name |
$1-$9 | Positional parameters |
$# | Number of arguments |
$@ | All arguments (as separate words) |
$* | All arguments (as single word) |
$$ | Current shell PID |
$! | Last background process PID |
$? | Last command exit status |
$- | Current shell options |
$_ | Last argument of previous command |
Variable Expansion
# Default value
${VAR:-default} # Use default if unset or empty
${VAR:=default} # Set and use default if unset or empty
${VAR:+value} # Use value if VAR is set
${VAR:?error} # Error if unset or empty
# String manipulation
${#VAR} # Length
${VAR#pattern} # Remove shortest prefix match
${VAR##pattern} # Remove longest prefix match
${VAR%pattern} # Remove shortest suffix match
${VAR%%pattern} # Remove longest suffix match
${VAR/pat/rep} # Replace first match
${VAR//pat/rep} # Replace all matchesTerminal Dimensions and Geometry
1. Getting Terminal Size
Unix/Linux (C)
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
struct winsize w;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == 0) {
printf("Rows: %d\n", w.ws_row);
printf("Columns: %d\n", w.ws_col);
printf("X pixels: %d\n", w.ws_xpixel);
printf("Y pixels: %d\n", w.ws_ypixel);
}
return 0;
}Bash
# Using tput
echo "Columns: $(tput cols)"
echo "Rows: $(tput lines)"
# Using stty
stty size # Returns: rows cols
# Using environment variables (may not be accurate)
echo "COLUMNS: $COLUMNS"
echo "LINES: $LINES"
# Force shell to update
shopt -s checkwinsizePython
import os
import shutil
# shutil method (Python 3.3+)
size = shutil.get_terminal_size()
print(f"Columns: {size.columns}, Rows: {size.lines}")
# os method
size = os.get_terminal_size()
print(f"Columns: {size.columns}, Lines: {size.lines}")
# Fallback with default
size = shutil.get_terminal_size(fallback=(80, 24))Node.js
// Get terminal size
const columns = process.stdout.columns;
const rows = process.stdout.rows;
// Listen for resize
process.stdout.on('resize', () => {
console.log(`New size: ${process.stdout.columns}x${process.stdout.rows}`);
});PowerShell
$host.UI.RawUI.WindowSize.Width # Columns
$host.UI.RawUI.WindowSize.Height # Rows
$host.UI.RawUI.BufferSize # Buffer dimensions
# Or using .NET
[Console]::WindowWidth
[Console]::WindowHeight2. Setting Terminal Size
# Using stty (sets COLUMNS and LINES)
stty rows 50 cols 132
# Using escape sequence (request terminal resize)
printf '\e[8;50;132t'
# Resize using escape sequence (xterm)
echo -e "\e[8;40;120t" # 40 rows, 120 cols3. Handling Terminal Resize
Signal Handling (Unix/Linux)
#include <signal.h>
#include <sys/ioctl.h>
#include <unistd.h>
volatile sig_atomic_t resize_flag = 0;
void handle_sigwinch(int sig) {
resize_flag = 1;
}
int main() {
struct sigaction sa;
sa.sa_handler = handle_sigwinch;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGWINCH, &sa, NULL);
while (1) {
if (resize_flag) {
resize_flag = 0;
struct winsize w;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
// Handle resize...
}
// Main loop...
}
}Bash
# Trap SIGWINCH
trap 'handle_resize' WINCH
handle_resize() {
COLUMNS=$(tput cols)
LINES=$(tput lines)
echo "Resized to ${COLUMNS}x${LINES}"
}Python
import signal
import shutil
def handle_resize(signum, frame):
size = shutil.get_terminal_size()
print(f"Resized to {size.columns}x{size.lines}")
signal.signal(signal.SIGWINCH, handle_resize)4. Common Terminal Dimensions
| Environment | Typical Size |
|---|---|
| Default terminal | 80x24 |
| Modern terminal | 120x40 |
| Maximized window | Varies |
| Serial console | 80x24 |
| Virtual console | 80x25 |
5. Escape Sequences for Size
Query Terminal Size
# Query cursor position (returns current position)
printf '\e[6n'
# Response: \e[{row};{col}R
# Query terminal size in cells (xterm)
printf '\e[18t'
# Response: \e[8;{rows};{cols}t
# Query terminal size in pixels (xterm)
printf '\e[14t'
# Response: \e[4;{height};{width}tSet Terminal Size
# Resize to rows x cols
printf '\e[8;{rows};{cols}t'
# Examples
printf '\e[8;24;80t' # Standard 80x24
printf '\e[8;50;120t' # Larger terminal6. The winsize Structure
struct winsize {
unsigned short ws_row; // Number of rows (lines)
unsigned short ws_col; // Number of columns
unsigned short ws_xpixel; // Horizontal size in pixels
unsigned short ws_ypixel; // Vertical size in pixels
};7. Buffer vs Window Size
On some systems, the buffer size differs from window size:
| Concept | Description |
|---|---|
| Window size | Visible area of terminal |
| Buffer size | Total scrollback buffer |
Windows Console
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hStdOut, &csbi);
// Window size
int windowCols = csbi.srWindow.Right - csbi.srWindow.Left + 1;
int windowRows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
// Buffer size
int bufferCols = csbi.dwSize.X;
int bufferRows = csbi.dwSize.Y;8. How Terminal Size Information Flows
Understanding how terminal size is communicated between components is essential for building responsive terminal applications.
Unix/Linux: The Complete Flow
The kernel maintains a winsize structure for each terminal device (PTY). This is stored in the PTY driver in the kernel, not in the shell or application.
┌─────────────────────────────────────────────────────────────┐
│ Terminal Emulator │
│ (knows actual window pixel size) │
│ │ │
│ User resizes ───────►│ │
│ window │ │
└─────────────────────────┼───────────────────────────────────┘
│
│ ioctl(TIOCSWINSZ, &winsize)
▼
┌─────────────────────────────────────────────────────────────┐
│ PTY Master │
│ (terminal emulator side) │
└─────────────────────────┼───────────────────────────────────┘
│
│ Kernel propagates to slave
│ and sends SIGWINCH to foreground
▼
┌─────────────────────────────────────────────────────────────┐
│ PTY Slave │
│ (shell/app side) │
│ │ │
│ ioctl(TIOCGWINSZ) to read size │
└─────────────────────────┼───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Shell / Application │
│ (bash, vim, htop, etc.) │
└─────────────────────────────────────────────────────────────┘The Key System Calls
Terminal emulator sets the size:
// Called by terminal emulator when window is resized
struct winsize ws = {.ws_row = 40, .ws_col = 120};
ioctl(pty_master_fd, TIOCSWINSZ, &ws);Application reads the size:
// Called by shell/application to get current size
struct winsize ws;
ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
printf("Size: %d rows x %d cols\n", ws.ws_row, ws.ws_col);How Resize Notification Works
When the terminal emulator updates the size via TIOCSWINSZ:
1. Kernel updates the winsize structure in the PTY driver 2. Kernel sends SIGWINCH (signal 28) to the foreground process group 3. Applications catch this signal and re-query the size
#include <signal.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <stdio.h>
volatile sig_atomic_t resize_needed = 0;
int current_rows, current_cols;
void handle_sigwinch(int sig) {
resize_needed = 1; // Set flag only - signal-safe
}
void update_size() {
struct winsize ws;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == 0) {
current_rows = ws.ws_row;
current_cols = ws.ws_col;
// Redraw with new dimensions
}
}
int main() {
signal(SIGWINCH, handle_sigwinch);
update_size(); // Get initial size
while (1) {
if (resize_needed) {
resize_needed = 0;
update_size();
printf("Resized to %dx%d\n", current_cols, current_rows);
}
// Main application loop...
}
}Calculating Characters from Pixels
The terminal emulator is the only component that knows actual pixel dimensions and font metrics. It calculates character dimensions:
columns = window_width_pixels / font_cell_width
rows = window_height_pixels / font_cell_heightExample: With a 12-pixel-wide font in a 960px window:
960 / 12 = 80 columnsWindows: Console Size Model
Windows uses a different model with the Console API. It distinguishes between:
- Buffer size: Total scrollback buffer dimensions
- Window size: Visible viewport dimensions
#include <windows.h>
CONSOLE_SCREEN_BUFFER_INFO csbi;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &csbi);
// Visible window size
int columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
int rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
// Total buffer size
int bufferWidth = csbi.dwSize.X;
int bufferHeight = csbi.dwSize.Y;Windows Resize Events
Windows uses console events instead of signals:
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD ir;
DWORD read;
// Enable window input events
DWORD mode;
GetConsoleMode(hIn, &mode);
SetConsoleMode(hIn, mode | ENABLE_WINDOW_INPUT);
while (ReadConsoleInput(hIn, &ir, 1, &read)) {
if (ir.EventType == WINDOW_BUFFER_SIZE_EVENT) {
COORD newSize = ir.Event.WindowBufferSizeEvent.dwSize;
printf("Resized to %dx%d\n", newSize.X, newSize.Y);
}
}Escape Sequence Query (Alternative Method)
When ioctl isn't available (e.g., over certain serial connections), applications can query the terminal directly using escape sequences:
# Method 1: Ask terminal for size directly (xterm)
printf '\e[18t'
# Response: ESC[8;rows;colst
# Method 2: Position cursor at far corner and query position
printf '\e[9999;9999H' # Move to (9999,9999) - will stop at actual max
printf '\e[6n' # Query cursor position
# Response: ESC[row;colRComponent Responsibilities Summary
| Component | Role |
|---|---|
| Terminal Emulator | Source of truth - calculates character size from pixels, calls ioctl(TIOCSWINSZ) |
| Kernel/PTY Driver | Stores the winsize structure, sends SIGWINCH on change |
| Shell/Application | Calls ioctl(TIOCGWINSZ) to read size, handles SIGWINCH |
The terminal emulator is the source of truth - it's the only component that actually knows the window's pixel dimensions and font metrics.
9. Responsive Terminal Applications
Best practices for handling terminal dimensions:
1. Query size on startup - Get initial dimensions 2. Handle SIGWINCH - React to resize events 3. Use relative positioning - Avoid hardcoded positions 4. Test edge cases - Very small/large terminals 5. Provide fallbacks - Default to 80x24 if unknown 6. Don't call unsafe functions in signal handlers - Set a flag and handle in main loop 7. Consider both Unix and Windows - Use appropriate APIs for each platform
Terminal Modes and Line Discipline
1. Terminal Modes Overview
Terminals can operate in different modes that control how input is processed:
| Mode | Description |
|---|---|
| Canonical (Cooked) | Line-by-line input with editing |
| Non-canonical (Raw) | Character-by-character input |
| cbreak | Partial raw mode |
2. Canonical vs Non-Canonical Mode
Canonical Mode (Default):
┌─────────────────────────────────────────┐
│ User types: H e l l o Enter │
│ │ │
│ ▼ │
│ Line buffer: "Hello\n" │
│ │ │
│ ▼ │
│ Application receives complete line │
└─────────────────────────────────────────┘
Non-Canonical Mode:
┌─────────────────────────────────────────┐
│ User types: H │
│ │ │
│ ▼ │
│ Application receives 'H' immediately │
│ │
│ User types: e │
│ │ │
│ ▼ │
│ Application receives 'e' immediately │
└─────────────────────────────────────────┘3. Terminal Attributes (termios)
#include <termios.h>
#include <unistd.h>
struct termios original, raw;
// Save original settings
tcgetattr(STDIN_FILENO, &original);
// Create raw mode settings
raw = original;
// Input flags
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
// Output flags
raw.c_oflag &= ~(OPOST);
// Control flags
raw.c_cflag |= (CS8);
// Local flags
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
// Control characters
raw.c_cc[VMIN] = 0; // Minimum chars to read
raw.c_cc[VTIME] = 1; // Timeout in 1/10 seconds
// Apply settings
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
// Restore original settings
tcsetattr(STDIN_FILENO, TCSAFLUSH, &original);4. termios Flags Reference
Input Flags (c_iflag)
| Flag | Description |
|---|---|
BRKINT | Signal on break |
ICRNL | Map CR to NL |
IGNBRK | Ignore break |
IGNCR | Ignore CR |
IGNPAR | Ignore parity errors |
INLCR | Map NL to CR |
INPCK | Enable parity checking |
ISTRIP | Strip 8th bit |
IXOFF | Enable start/stop input |
IXON | Enable start/stop output |
PARMRK | Mark parity errors |
Output Flags (c_oflag)
| Flag | Description |
|---|---|
OPOST | Post-process output |
ONLCR | Map NL to CR-NL |
OCRNL | Map CR to NL |
ONOCR | No CR at column 0 |
ONLRET | NL performs CR |
OFILL | Use fill characters |
Control Flags (c_cflag)
| Flag | Description |
|---|---|
CSIZE | Character size mask (CS5, CS6, CS7, CS8) |
CSTOPB | 2 stop bits |
CREAD | Enable receiver |
PARENB | Enable parity |
PARODD | Odd parity |
HUPCL | Hangup on close |
CLOCAL | Ignore modem control lines |
Local Flags (c_lflag)
| Flag | Description |
|---|---|
ECHO | Enable echo |
ECHOE | Echo erase as BS-SP-BS |
ECHOK | Echo NL after kill |
ECHONL | Echo NL |
ICANON | Canonical mode |
IEXTEN | Extended functions |
ISIG | Enable signals |
NOFLSH | Disable flush after interrupt |
TOSTOP | Background write sends SIGTTOU |
5. Control Characters (c_cc)
| Index | Default | Description |
|---|---|---|
VEOF | Ctrl+D | End of file |
VEOL | Additional end of line | |
VERASE | Ctrl+H/DEL | Erase character |
VINTR | Ctrl+C | Interrupt |
VKILL | Ctrl+U | Kill line |
VMIN | 1 | Minimum chars for read |
VQUIT | Ctrl+\ | Quit |
VSTART | Ctrl+Q | Resume output |
VSTOP | Ctrl+S | Suspend output |
VSUSP | Ctrl+Z | Suspend |
VTIME | 0 | Read timeout |
6. Using stty
# Display all settings
stty -a
# Display settings in parseable form
stty -g
# Enable raw mode
stty raw
# Enable cooked mode
stty cooked
# Disable echo
stty -echo
# Enable echo
stty echo
# Set special characters
stty erase ^H # Set erase character
stty intr ^C # Set interrupt character
stty eof ^D # Set EOF character
# Set character size
stty cs8 # 8-bit characters
# Set baud rate
stty 115200
# Save and restore settings
saved=$(stty -g)
stty raw
# ... do something
stty "$saved"7. Common Mode Configurations
Raw Mode
stty raw -echo
# Or in C:
# c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG)
# c_iflag &= ~(IXON | ICRNL)Cbreak Mode
Like raw mode but keeps signal processing:
stty -icanon min 1
# Or in C:
# c_lflag &= ~(ICANON | ECHO)
# Keep ISIG setPassword Input
stty -echo
read -s password
stty echo8. Python termios Example
import sys
import tty
import termios
def get_char():
"""Read a single character without waiting for Enter."""
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
def get_password():
"""Read password with echo disabled."""
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
new = termios.tcgetattr(fd)
new[3] &= ~termios.ECHO # Disable echo
termios.tcsetattr(fd, termios.TCSADRAIN, new)
password = input()
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return password9. tcsetattr Timing
| Mode | Description |
|---|---|
TCSANOW | Change immediately |
TCSADRAIN | Change after output drain |
TCSAFLUSH | Change after output drain, discard input |
Job Control and Process Management
1. Process Groups and Sessions
Session (SID)
├── Process Group 1 (Foreground)
│ ├── Process A (Group Leader)
│ └── Process B
├── Process Group 2 (Background Job 1)
│ └── Process C
└── Process Group 3 (Background Job 2)
├── Process D (Group Leader)
└── Process E2. Key Concepts
| Concept | Description |
|---|---|
| Session | Collection of process groups, led by login shell |
| Session Leader | Process that created the session (usually the shell) |
| Process Group | Collection of related processes (a job) |
| Foreground Group | The process group receiving terminal input |
| Background Group | Process groups not receiving terminal input |
| Controlling Terminal | Terminal associated with the session |
3. Job Control Commands
# Run command in background
command &
# List jobs
jobs
jobs -l # Include PIDs
jobs -p # Only PIDs
# Bring job to foreground
fg %1 # Job number 1
fg %+ # Current job
fg %- # Previous job
fg %cmd # Job starting with "cmd"
fg %% # Current job
# Send job to background
bg %1
bg # Current stopped job
# Suspend current job
Ctrl+Z # Sends SIGTSTP
# Disown job (detach from shell)
disown %1
disown -a # All jobs
disown -h # Mark job to not receive SIGHUP
# Wait for job
wait %1
wait $pid
wait # Wait for all background jobs4. Job Specifiers
| Specifier | Description |
|---|---|
%n | Job number n |
%+ or %% | Current job |
%- | Previous job |
%string | Job beginning with string |
%?string | Job containing string |
5. Process States
┌───────────────────────────────────────────────────┐
│ │
▼ │
┌───────┐ fork() ┌───────┐ │
│ READY │◄────────────│ NEW │ │
└───┬───┘ └───────┘ │
│ │
│ scheduled │
▼ │
┌───────┐ │
│RUNNING│──────────────────────────────────────────────┤
└───┬───┘ │
│ │
├──── I/O or event wait ────►┌─────────┐ │
│ │ WAITING │───────────┘
│ └─────────┘ event complete
│
├──── SIGSTOP/SIGTSTP ──────►┌─────────┐
│ │ STOPPED │
│◄───── SIGCONT ────────────└─────────┘
│
│
▼
┌────────┐ wait() ┌────────┐
│ ZOMBIE │─────────────►│REMOVED │
└────────┘ └────────┘6. Process Control System Calls
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
// Get IDs
pid_t pid = getpid(); // Process ID
pid_t ppid = getppid(); // Parent process ID
pid_t pgid = getpgrp(); // Process group ID
pid_t sid = getsid(0); // Session ID
// Set process group
setpgid(pid, pgid);
setpgid(0, 0); // Make current process group leader
// Create new session
setsid(); // Creates new session, becomes session leader
// Set foreground process group
tcsetpgrp(STDIN_FILENO, pgid);
// Get foreground process group
pid_t fg_pgid = tcgetpgrp(STDIN_FILENO);7. The nohup Command
# Run command immune to hangups
nohup command &
# Output goes to nohup.out by default
nohup command > output.log 2>&1 &
# Modern alternative: disown
command &
disown
# Or prevent hangup signal
command &
disown -h8. Background Processes
Running in Background
# Start in background
command &
# Move running process to background
Ctrl+Z # Suspend
bg # Resume in background
# Keep running after terminal closes
nohup command &
# or
command & disown
# or
setsid commandBackground Process I/O
Background processes that try to read from terminal receive SIGTTIN:
# This will be stopped
cat & # Tries to read stdin, receives SIGTTIN
# Solution: redirect input
cat < input.txt &9. Process Priority (Nice)
# Start with lower priority
nice -n 10 command
# Change priority of running process
renice -n 10 -p $PID
# Nice values: -20 (highest) to 19 (lowest)
# Only root can set negative values10. Daemon Creation
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
void daemonize() {
// Fork and exit parent
pid_t pid = fork();
if (pid < 0) exit(EXIT_FAILURE);
if (pid > 0) exit(EXIT_SUCCESS);
// Create new session
if (setsid() < 0) exit(EXIT_FAILURE);
// Fork again to prevent terminal acquisition
pid = fork();
if (pid < 0) exit(EXIT_FAILURE);
if (pid > 0) exit(EXIT_SUCCESS);
// Set file permissions
umask(0);
// Change to root directory
chdir("/");
// Close standard file descriptors
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
// Redirect to /dev/null
open("/dev/null", O_RDONLY); // stdin
open("/dev/null", O_WRONLY); // stdout
open("/dev/null", O_WRONLY); // stderr
}11. Process Information
# View process tree
pstree
pstree -p # With PIDs
pstree -u # With usernames
# View sessions and process groups
ps -eo pid,ppid,pgid,sid,comm
# View job control info
ps -j
# Interactive process viewer
top
htop12. Checking Process State
# Check if process exists
kill -0 $PID 2>/dev/null && echo "Running" || echo "Not running"
# Get process state
ps -p $PID -o state=
# States: R (running), S (sleeping), D (disk sleep), Z (zombie), T (stopped)Environment Variables
1. Key Terminal Environment Variables
| Variable | Description |
|---|---|
TERM | Terminal type (e.g., xterm-256color, vt100) |
SHELL | User's default shell path |
PATH | Executable search path |
HOME | User's home directory |
USER | Current username |
LANG | Locale setting |
LC_* | Locale category settings |
COLUMNS | Terminal width (may not be auto-updated) |
LINES | Terminal height (may not be auto-updated) |
PS1 | Primary prompt string |
PS2 | Secondary prompt string |
PWD | Current working directory |
OLDPWD | Previous working directory |
DISPLAY | X11 display server |
COLORTERM | Color terminal type |
TERM_PROGRAM | Terminal emulator name |
2. Working with Environment Variables
Bash
# Set variable
export VAR="value"
VAR="value" # Shell variable (not exported)
# Read variable
echo "$VAR"
echo "${VAR}"
echo "${VAR:-default}" # Default if unset
# Unset variable
unset VAR
# List all environment variables
env
printenv
export -p
# Set for single command
VAR=value command
# Check if set
if [[ -v VAR ]]; then
echo "VAR is set"
fi
if [[ -z "${VAR+x}" ]]; then
echo "VAR is unset"
fiZsh
# Similar to bash
export VAR="value"
# Associative arrays for environment
typeset -A myarray
export myarray
# List exported variables
exportFish
# Set variable
set -x VAR "value" # Export (environment)
set VAR "value" # Local variable
set -gx VAR "value" # Global and exported
# Unset
set -e VAR
# List
set -x # Show exportedPowerShell
# Set variable
$env:VAR = "value"
# Read variable
$env:VAR
$env:PATH
# Remove variable
Remove-Item Env:VAR
# List all
Get-ChildItem Env:
[Environment]::GetEnvironmentVariables()
# Permanent setting
[Environment]::SetEnvironmentVariable("VAR", "value", "User")
[Environment]::SetEnvironmentVariable("VAR", "value", "Machine")C
#include <stdlib.h>
// Get variable
char *value = getenv("PATH");
// Set variable
setenv("VAR", "value", 1); // 1 = overwrite existing
putenv("VAR=value"); // Alternative
// Unset variable
unsetenv("VAR");Python
import os
# Get variable
value = os.environ.get('VAR', 'default')
value = os.environ['VAR'] # Raises KeyError if not set
# Set variable
os.environ['VAR'] = 'value'
# Delete variable
del os.environ['VAR']
# List all
for key, value in os.environ.items():
print(f"{key}={value}")3. TERM Variable and terminfo
The TERM variable specifies the terminal type, used to look up capabilities:
# Common TERM values
xterm
xterm-256color
screen
screen-256color
tmux
tmux-256color
vt100
dumb
linux
# Query terminal capabilities
infocmp $TERM
# Get specific capability
tput colors # Number of colors
tput cols # Columns
tput lines # Lines
tput bold # Bold capability
tput sgr0 # Reset
# Terminfo database locations
/usr/share/terminfo/
/lib/terminfo/
~/.terminfo/4. PATH Variable
# View PATH
echo "$PATH"
echo "$PATH" | tr ':' '\n' # One per line
# Add to PATH
export PATH="$PATH:/new/path" # Append
export PATH="/new/path:$PATH" # Prepend
# Remove duplicates (bash)
PATH=$(echo "$PATH" | tr ':' '\n' | sort -u | tr '\n' ':')5. Locale Variables
| Variable | Description |
|---|---|
LANG | Default locale |
LC_ALL | Override all LC_* |
LC_COLLATE | Sorting order |
LC_CTYPE | Character classification |
LC_MESSAGES | Message language |
LC_MONETARY | Money formatting |
LC_NUMERIC | Number formatting |
LC_TIME | Date/time formatting |
# View locale settings
locale
# Set UTF-8 locale
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
# List available locales
locale -a6. Prompt Customization
Bash PS1
# Escape sequences for PS1
\u # Username
\h # Hostname (short)
\H # Hostname (full)
\w # Current directory (full)
\W # Current directory (basename)
\d # Date
\t # Time (24h)
\T # Time (12h)
\@ # Time (12h AM/PM)
\n # Newline
\$ # $ (or # for root)
\! # History number
\# # Command number
# Example
export PS1='\u@\h:\w\$ 'Zsh PROMPT
# Prompt escape sequences
%n # Username
%m # Hostname (short)
%M # Hostname (full)
%~ # Current directory (~ for home)
%/ # Current directory (full)
%d # Current directory (full)
%* # Time (24h with seconds)
%D # Date
# Example
export PROMPT='%n@%m:%~%# '7. Environment Inheritance
Parent Process
├── VAR1=value1
├── VAR2=value2
│
└── Child Process (fork)
├── VAR1=value1 (inherited)
├── VAR2=value2 (inherited)
└── VAR3=value3 (new, not in parent)8. Common Patterns
Check Variable Set
# Check if set (empty or not)
if [[ -v VAR ]]; then
echo "VAR is set (possibly empty)"
fi
# Check if set and non-empty
if [[ -n "${VAR:-}" ]]; then
echo "VAR is set and non-empty"
fi
# Check if unset or empty
if [[ -z "${VAR:-}" ]]; then
echo "VAR is unset or empty"
fiDefault Values
# Use default if unset or empty
echo "${VAR:-default}"
# Set default if unset or empty
: "${VAR:=default}"
# Error if unset or empty
echo "${VAR:?Variable not set}"
# Use alternate if set and non-empty
echo "${VAR:+alternate}"Exporting Functions (Bash)
# Export function
my_func() {
echo "Hello"
}
export -f my_func
# Now available in subshells
bash -c 'my_func'Signal Handling
1. Terminal-Related Signals
| Signal | Number | Default Action | Keyboard | Description |
|---|---|---|---|---|
SIGHUP | 1 | Terminate | Hangup (terminal closed) | |
SIGINT | 2 | Terminate | Ctrl+C | Interrupt |
SIGQUIT | 3 | Core dump | Ctrl+\ | Quit |
SIGKILL | 9 | Terminate | Kill (cannot be caught) | |
SIGTERM | 15 | Terminate | Graceful termination | |
SIGTSTP | 20 | Stop | Ctrl+Z | Terminal stop |
SIGCONT | 18 | Continue | Continue if stopped | |
SIGTTIN | 21 | Stop | Background read from terminal | |
SIGTTOU | 22 | Stop | Background write to terminal | |
SIGWINCH | 28 | Ignore | Window size changed | |
SIGPIPE | 13 | Terminate | Broken pipe | |
SIGCHLD | 17 | Ignore | Child process status changed |
2. Signal Handling in Different Environments
Bash
# Trap signals
trap 'echo "Caught SIGINT"' INT
trap 'echo "Caught SIGTERM"' TERM
trap 'cleanup' EXIT
# Ignore signal
trap '' INT
# Reset to default
trap - INT
# List traps
trap -p
# Trap multiple signals
trap 'handler' INT TERM HUP
# Common patterns
cleanup() {
echo "Cleaning up..."
rm -f /tmp/tempfile.$$
}
trap cleanup EXITC
#include <signal.h>
#include <stdio.h>
void handler(int sig) {
printf("Caught signal %d\n", sig);
}
int main() {
// Simple handler
signal(SIGINT, handler);
// Using sigaction (preferred)
struct sigaction sa;
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART; // Restart interrupted syscalls
sigaction(SIGINT, &sa, NULL);
// Ignore signal
signal(SIGINT, SIG_IGN);
// Default handling
signal(SIGINT, SIG_DFL);
while(1) pause();
}Python
import signal
import sys
def handler(signum, frame):
print(f"Caught signal {signum}")
sys.exit(0)
# Register handler
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
# Ignore signal
signal.signal(signal.SIGPIPE, signal.SIG_IGN)
# Use default handler
signal.signal(signal.SIGINT, signal.SIG_DFL)
# Context manager for temporary handler
from contextlib import contextmanager
@contextmanager
def signal_handler(sig, handler):
old_handler = signal.signal(sig, handler)
try:
yield
finally:
signal.signal(sig, old_handler)Node.js
// Handle signals
process.on('SIGINT', () => {
console.log('Caught SIGINT');
process.exit(0);
});
process.on('SIGTERM', () => {
console.log('Caught SIGTERM');
// Graceful shutdown
server.close(() => {
process.exit(0);
});
});
// Ignore SIGPIPE
process.on('SIGPIPE', () => {});3. Sending Signals
# By PID
kill -SIGTERM 1234
kill -15 1234
kill 1234 # SIGTERM by default
# By name
kill -SIGKILL 1234
kill -9 1234
# To process group
kill -SIGTERM -1234
# To job
kill %1
# Common signals
kill -SIGHUP 1234 # Reload configuration
kill -SIGINT 1234 # Interrupt (like Ctrl+C)
kill -SIGTERM 1234 # Graceful termination
kill -SIGKILL 1234 # Force kill (cannot be caught)
kill -SIGSTOP 1234 # Pause process (cannot be caught)
kill -SIGCONT 1234 # Resume process
kill -SIGUSR1 1234 # User-defined signal 1
kill -SIGUSR2 1234 # User-defined signal 2
# pkill and killall
pkill -SIGTERM processname
pkill -f "pattern" # Match full command line
killall -SIGTERM processname4. Signal Numbers
| Signal | Linux | macOS |
|---|---|---|
| SIGHUP | 1 | 1 |
| SIGINT | 2 | 2 |
| SIGQUIT | 3 | 3 |
| SIGKILL | 9 | 9 |
| SIGUSR1 | 10 | 30 |
| SIGUSR2 | 12 | 31 |
| SIGTERM | 15 | 15 |
| SIGCHLD | 17 | 20 |
| SIGCONT | 18 | 19 |
| SIGSTOP | 19 | 17 |
| SIGTSTP | 20 | 18 |
| SIGWINCH | 28 | 28 |
# List all signals
kill -l
# Get signal number
kill -l SIGTERM # Returns 155. Signal Safety
Async-Signal-Safe Functions
Only certain functions are safe to call from signal handlers:
// Safe to call
_exit(), write(), signal()
// NOT safe (may cause undefined behavior)
printf(), malloc(), free()Safe Signal Handler Pattern
volatile sig_atomic_t got_signal = 0;
void handler(int sig) {
got_signal = 1; // Just set flag
}
int main() {
signal(SIGINT, handler);
while (!got_signal) {
// Main loop
}
// Handle signal safely here
printf("Signal received\n");
}6. Signal Masks
#include <signal.h>
sigset_t set, oldset;
// Initialize empty set
sigemptyset(&set);
// Add signal to set
sigaddset(&set, SIGINT);
sigaddset(&set, SIGTERM);
// Block signals
sigprocmask(SIG_BLOCK, &set, &oldset);
// Critical section - signals blocked
// Unblock signals
sigprocmask(SIG_SETMASK, &oldset, NULL);
// Wait for signal
int sig;
sigwait(&set, &sig);7. Common Patterns
Graceful Shutdown
#!/bin/bash
cleanup() {
echo "Shutting down..."
# Stop services
# Save state
# Remove temp files
exit 0
}
trap cleanup SIGINT SIGTERM
# Main application
while true; do
# do work
sleep 1
doneReload Configuration
#!/bin/bash
reload_config() {
echo "Reloading configuration..."
source /etc/myapp/config
}
trap reload_config SIGHUP
while true; do
# Main loop
sleep 1
doneChild Process Handling
void sigchld_handler(int sig) {
int status;
pid_t pid;
// Reap all terminated children
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
if (WIFEXITED(status)) {
printf("Child %d exited with %d\n",
pid, WEXITSTATUS(status));
}
}
}
int main() {
struct sigaction sa;
sa.sa_handler = sigchld_handler;
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, NULL);
// ...
}8. Real-time Signals
// Real-time signals: SIGRTMIN to SIGRTMAX
// Guaranteed delivery and queuing
union sigval value;
value.sival_int = 42;
sigqueue(pid, SIGRTMIN, value);Escape Sequences and Control Characters
1. Control Characters
| Char | Ctrl+ | ASCII | Name | Description |
|---|---|---|---|---|
^@ | Ctrl+@ | 0 | NUL | Null |
^A | Ctrl+A | 1 | SOH | Start of heading |
^B | Ctrl+B | 2 | STX | Start of text |
^C | Ctrl+C | 3 | ETX | Interrupt (SIGINT) |
^D | Ctrl+D | 4 | EOT | End of file/input |
^E | Ctrl+E | 5 | ENQ | Enquiry |
^F | Ctrl+F | 6 | ACK | Acknowledge |
^G | Ctrl+G | 7 | BEL | Bell (beep) |
^H | Ctrl+H | 8 | BS | Backspace |
^I | Ctrl+I | 9 | TAB | Horizontal tab |
^J | Ctrl+J | 10 | LF | Line feed (newline) |
^K | Ctrl+K | 11 | VT | Vertical tab |
^L | Ctrl+L | 12 | FF | Form feed (clear screen) |
^M | Ctrl+M | 13 | CR | Carriage return |
^N | Ctrl+N | 14 | SO | Shift out |
^O | Ctrl+O | 15 | SI | Shift in |
^Q | Ctrl+Q | 17 | DC1 | Resume output (XON) |
^S | Ctrl+S | 19 | DC3 | Pause output (XOFF) |
^U | Ctrl+U | 21 | NAK | Kill line |
^W | Ctrl+W | 23 | ETB | Delete word |
^Z | Ctrl+Z | 26 | SUB | Suspend (SIGTSTP) |
^[ | Ctrl+[ | 27 | ESC | Escape |
^\ | Ctrl+\ | 28 | FS | Quit (SIGQUIT) |
^? | 127 | DEL | Delete |
2. ANSI Escape Sequences
All ANSI sequences start with ESC (\e, \033, \x1b) followed by [ (CSI - Control Sequence Introducer).
Escape Representations
| Format | Example | Description |
|---|---|---|
\e | \e[31m | Bash/shell |
\033 | \033[31m | Octal |
\x1b | \x1b[31m | Hexadecimal |
^[ | ^[[31m | Caret notation |
3. Cursor Movement
# Move cursor
\e[H # Home (1,1)
\e[{r};{c}H # Move to row r, column c
\e[{r};{c}f # Same as H
\e[{n}A # Move up n lines
\e[{n}B # Move down n lines
\e[{n}C # Move forward n columns
\e[{n}D # Move backward n columns
\e[{n}E # Move to beginning of line n down
\e[{n}F # Move to beginning of line n up
\e[{n}G # Move to column n
# Save/restore cursor
\e[s # Save cursor position (SCO)
\e[u # Restore cursor position (SCO)
\e7 # Save cursor (DEC)
\e8 # Restore cursor (DEC)4. Screen Clearing
\e[J # Clear from cursor to end of screen
\e[0J # Same as above
\e[1J # Clear from cursor to beginning of screen
\e[2J # Clear entire screen
\e[3J # Clear entire screen and scrollback
\e[K # Clear from cursor to end of line
\e[0K # Same as above
\e[1K # Clear from cursor to beginning of line
\e[2K # Clear entire line5. Text Formatting (SGR - Select Graphic Rendition)
# Format: \e[{attr1};{attr2};...m
\e[0m # Reset all attributes
\e[1m # Bold
\e[2m # Dim
\e[3m # Italic
\e[4m # Underline
\e[5m # Blink
\e[7m # Reverse video
\e[8m # Hidden
\e[9m # Strikethrough
\e[22m # Normal intensity (not bold/dim)
\e[23m # Not italic
\e[24m # Not underlined
\e[25m # Not blinking
\e[27m # Not reversed
\e[28m # Not hidden
\e[29m # Not strikethrough6. Colors
4-bit Colors (16 colors)
# Foreground: 30-37, 90-97 (bright)
# Background: 40-47, 100-107 (bright)
\e[30m # Black
\e[31m # Red
\e[32m # Green
\e[33m # Yellow
\e[34m # Blue
\e[35m # Magenta
\e[36m # Cyan
\e[37m # White
\e[39m # Default foreground
\e[40m # Black background
\e[41m # Red background
\e[42m # Green background
\e[43m # Yellow background
\e[44m # Blue background
\e[45m # Magenta background
\e[46m # Cyan background
\e[47m # White background
\e[49m # Default background
# Bright versions
\e[90m # Bright black (gray)
\e[91m # Bright red
...
\e[97m # Bright white8-bit Colors (256 colors)
\e[38;5;{n}m # Foreground (n = 0-255)
\e[48;5;{n}m # Background (n = 0-255)
# Color ranges:
# 0-7: Standard colors
# 8-15: High intensity colors
# 16-231: 216 colors (6x6x6 cube)
# 232-255: Grayscale (24 shades)24-bit True Color
\e[38;2;{r};{g};{b}m # Foreground RGB
\e[48;2;{r};{g};{b}m # Background RGB
# Example: Orange text
printf '\e[38;2;255;165;0mOrange text\e[0m\n'7. Using tput for Portable Sequences
# Colors
tput setaf 1 # Red foreground
tput setab 4 # Blue background
tput sgr0 # Reset
# Formatting
tput bold # Bold
tput dim # Dim
tput smul # Start underline
tput rmul # End underline
tput rev # Reverse
tput smso # Start standout
tput rmso # End standout
# Cursor
tput cup 10 20 # Move to row 10, col 20
tput home # Move to 0,0
tput sc # Save cursor
tput rc # Restore cursor
tput civis # Hide cursor
tput cnorm # Show cursor
# Screen
tput clear # Clear screen
tput el # Clear to end of line
tput ed # Clear to end of screen
tput smcup # Enter alternate screen
tput rmcup # Exit alternate screen8. Alternate Screen Buffer
Many terminal applications use an alternate screen buffer:
# Enter alternate screen
tput smcup
# or
printf '\e[?1049h'
# Exit alternate screen
tput rmcup
# or
printf '\e[?1049l'9. Cursor Visibility
# Hide cursor
printf '\e[?25l'
tput civis
# Show cursor
printf '\e[?25h'
tput cnorm10. Scrolling
# Set scrolling region (rows n to m)
\e[{n};{m}r
# Scroll up n lines
\e[{n}S
# Scroll down n lines
\e[{n}T
# Reset scrolling region
\e[r11. Terminal Queries
# Query cursor position
printf '\e[6n'
# Response: \e[{row};{col}R
# Query terminal type
printf '\e[c'
# Response: \e[?{params}c
# Query terminal size (xterm)
printf '\e[18t'
# Response: \e[8;{rows};{cols}t12. OSC Sequences (Operating System Commands)
# Set window title
printf '\e]0;Window Title\a'
printf '\e]2;Window Title\a'
# Set icon name
printf '\e]1;Icon Name\a'
# Hyperlinks (some terminals)
printf '\e]8;;https://example.com\e\\Link Text\e]8;;\e\\'13. Common Patterns
Progress Bar
progress_bar() {
local width=50
local percent=$1
local filled=$((width * percent / 100))
local empty=$((width - filled))
printf "\r["
printf "%${filled}s" | tr ' ' '#'
printf "%${empty}s" | tr ' ' '-'
printf "] %3d%%" "$percent"
}Spinner
spinner() {
local chars='|/-\'
local i=0
while true; do
printf "\r${chars:$i:1}"
i=$(((i + 1) % 4))
sleep 0.1
done
}Colored Output Function
color() {
local color=$1
shift
local text="$*"
case $color in
red) printf '\e[31m%s\e[0m' "$text" ;;
green) printf '\e[32m%s\e[0m' "$text" ;;
yellow) printf '\e[33m%s\e[0m' "$text" ;;
blue) printf '\e[34m%s\e[0m' "$text" ;;
*) printf '%s' "$text" ;;
esac
}Redirection and Pipes
1. Basic Redirection (Bash)
# Output redirection
command > file # Redirect stdout (overwrite)
command >> file # Redirect stdout (append)
command 2> file # Redirect stderr
command 2>> file # Redirect stderr (append)
command &> file # Redirect both stdout and stderr
command > file 2>&1 # Redirect stderr to stdout
command &>> file # Append both (Bash 4+)
# Input redirection
command < file # Redirect stdin from file
command << EOF # Here document
content
EOF
command <<< "string" # Here string
# Null redirection
command > /dev/null # Discard stdout
command 2> /dev/null # Discard stderr
command &> /dev/null # Discard both2. File Descriptor Manipulation
# File descriptor manipulation
exec 3> file # Open fd 3 for writing
exec 3< file # Open fd 3 for reading
exec 3<> file # Open fd 3 for read/write
exec 3>&- # Close fd 3
# Duplicate file descriptors
command 2>&1 # Duplicate fd 1 to fd 2
command >&2 # Redirect stdout to stderr
# Move file descriptors
exec 3>&1 # Copy stdout to fd 3
exec 1>&4 # Restore stdout from fd 4
# Open file for specific purpose
exec 3< input.txt # Open for reading
exec 4> output.txt # Open for writing
read line <&3 # Read from fd 3
echo "data" >&4 # Write to fd 4
exec 3<&- # Close fd 3
exec 4>&- # Close fd 43. Advanced Redirection
# Swap stdout and stderr
command 3>&1 1>&2 2>&3 3>&-
# Redirect to multiple destinations
command | tee file # stdout to file and stdout
command | tee -a file # Append
command 2>&1 | tee file # Both streams
# Process substitution
diff <(command1) <(command2) # Compare outputs
command > >(process) # Output through process
command < <(process) # Input from process
# Named pipes (FIFOs)
mkfifo mypipe
command1 > mypipe &
command2 < mypipe
rm mypipe4. Here Documents
# Basic here document
cat << EOF
Line 1
Line 2
Variable: $VAR
EOF
# Quoted delimiter (no expansion)
cat << 'EOF'
Line 1
$VAR is not expanded
EOF
# Remove leading tabs
cat <<- EOF
This line has a tab
Tabs are removed
EOF5. Pipes
# Simple pipe
command1 | command2
# Pipeline with error handling
set -o pipefail
command1 | command2 | command3
# Check individual exit codes
cmd1 | cmd2 | cmd3
echo "${PIPESTATUS[@]}" # Array of exit codes
echo "${PIPESTATUS[0]}" # First command's exit code
# Named pipe (FIFO)
mkfifo /tmp/mypipe
producer > /tmp/mypipe &
consumer < /tmp/mypipe6. Tee and Process Substitution
# tee - split output
command | tee file # Write to file and stdout
command | tee file1 file2 # Multiple files
command | tee -a file # Append
command 2>&1 | tee file # Include stderr
# Process substitution
# Write to multiple processes
command | tee >(process1) >(process2) > /dev/null
# Compare outputs
diff <(sort file1) <(sort file2)
# Log and display
command | tee >(logger -t myapp)7. PowerShell Redirection
# Output streams in PowerShell
# 1 - Success output (stdout)
# 2 - Error output (stderr)
# 3 - Warning
# 4 - Verbose
# 5 - Debug
# 6 - Information
# * - All streams
# Redirection
command > file # Redirect success stream
command 2> file # Redirect error stream
command *> file # Redirect all streams
command >> file # Append
# Redirect to $null (discard)
command > $null
command 2> $null
# Redirect stream to another stream
command 2>&1 # Errors to success stream
# Piping (object pipeline, not text)
Get-Process | Where-Object {$_.CPU -gt 100} | Sort-Object CPU8. Windows cmd.exe Redirection
:: Output redirection
command > file
command >> file :: Append
command 2> file :: Stderr
command 2>&1 :: Stderr to stdout
command > file 2>&1 :: Both to file
:: Input redirection
command < file
:: Pipe
command1 | command2
:: NUL device (like /dev/null)
command > NUL
command 2> NUL9. Common Patterns
Log Both to File and Display
# Using tee
command 2>&1 | tee -a logfile
# Using process substitution
command > >(tee -a stdout.log) 2> >(tee -a stderr.log >&2)Capture Output and Exit Code
# Capture output
output=$(command)
exitcode=$?
# Capture with stderr
output=$(command 2>&1)
# Capture separately
{ output=$(command 2>&1 1>&3 3>&-); } 3>&1
stderr=$outputRedirect Stdout and Stderr to Different Files
command > stdout.log 2> stderr.logFilter Errors
# Show only errors
command 2>&1 >/dev/null
# Suppress only errors
command 2>/dev/nullAppend with Timestamp
command 2>&1 | while read line; do
echo "$(date '+%Y-%m-%d %H:%M:%S') $line"
done >> logfile10. Special File Descriptors
| Path | Description |
|---|---|
/dev/stdin | Standard input (fd 0) |
/dev/stdout | Standard output (fd 1) |
/dev/stderr | Standard error (fd 2) |
/dev/null | Discard output |
/dev/zero | Infinite zeros |
/dev/tty | Current terminal |
/dev/fd/N | File descriptor N |
11. Coprocess
# Bash coprocess
coproc myproc { command; }
echo "input" >&${myproc[1]}
read output <&${myproc[0]}Windows-Specific Concepts
1. Console Architecture
┌─────────────────────────────────────────┐
│ Console Host (conhost.exe) │
│ or Windows Terminal │
├─────────────────────────────────────────┤
│ Console API │
│ (kernel32.dll functions) │
├─────────────────────────────────────────┤
│ ConDrv │
│ (Console Driver) │
├─────────────────────────────────────────┤
│ Console Application │
│ (cmd.exe, PowerShell, etc.) │
└─────────────────────────────────────────┘2. Console API Functions (Win32)
#include <windows.h>
// Handle retrieval
HANDLE hStdIn = GetStdHandle(STD_INPUT_HANDLE);
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE hStdErr = GetStdHandle(STD_ERROR_HANDLE);
// Console buffer info
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hStdOut, &csbi);
int columns = csbi.srWindow.Right - csbi.srWindow.Left + 1;
int rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
// Set cursor position
COORD pos = {10, 5};
SetConsoleCursorPosition(hStdOut, pos);
// Set text attributes
SetConsoleTextAttribute(hStdOut,
FOREGROUND_RED | FOREGROUND_INTENSITY);
// Console mode
DWORD mode;
GetConsoleMode(hStdIn, &mode);
SetConsoleMode(hStdIn, mode | ENABLE_VIRTUAL_TERMINAL_INPUT);3. Console Modes (Windows)
Input Modes
// Input mode flags
ENABLE_ECHO_INPUT // Echo typed characters
ENABLE_INSERT_MODE // Insert mode
ENABLE_LINE_INPUT // Line input mode (canonical)
ENABLE_MOUSE_INPUT // Mouse events
ENABLE_PROCESSED_INPUT // Process Ctrl+C
ENABLE_QUICK_EDIT_MODE // Mouse selection
ENABLE_VIRTUAL_TERMINAL_INPUT // VT input sequences
ENABLE_WINDOW_INPUT // Window resize eventsOutput Modes
// Output mode flags
ENABLE_PROCESSED_OUTPUT // Process control characters
ENABLE_WRAP_AT_EOL_OUTPUT // Wrap at end of line
ENABLE_VIRTUAL_TERMINAL_PROCESSING // VT sequences
DISABLE_NEWLINE_AUTO_RETURN // Don't auto CR on LFEnabling VT Processing
// Enable VT processing for ANSI escape sequences
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode;
GetConsoleMode(hOut, &mode);
SetConsoleMode(hOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
// Now ANSI sequences work
printf("\x1b[31mRed text\x1b[0m\n");4. Virtual Terminal Sequences (Windows 10+)
Windows 10 and later support ANSI/VT100 escape sequences:
// Enable VT processing
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
DWORD mode;
GetConsoleMode(hOut, &mode);
SetConsoleMode(hOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
// Now ANSI sequences work
printf("\x1b[31mRed text\x1b[0m\n");PowerShell
# VT sequences work in Windows Terminal and modern consoles
Write-Host "`e[31mRed text`e[0m"
# Or using $PSStyle (PowerShell 7.2+)
$PSStyle.Foreground.Red + "Red text" + $PSStyle.Reset5. Windows Terminal vs ConHost
| Feature | ConHost (Legacy) | Windows Terminal |
|---|---|---|
| VT Sequences | Partial (Win10+) | Full |
| True Color | Limited | Yes |
| Tabs | No | Yes |
| GPU Acceleration | No | Yes |
| Unicode | Partial | Full |
| Customization | Limited | Extensive |
| Profiles | No | Yes |
| Panes | No | Yes |
6. ConPTY (Pseudo Console)
Windows 10 introduced ConPTY for better PTY emulation:
#include <windows.h>
#include <consoleapi.h>
HPCON hPC;
HRESULT hr;
// Create pipes for I/O
HANDLE hPipeIn, hPipeOut;
// ... CreatePipe setup ...
// Create pseudo console
COORD size = {80, 24};
hr = CreatePseudoConsole(size, hPipeIn, hPipeOut, 0, &hPC);
// Attach to process via PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
// Resize
hr = ResizePseudoConsole(hPC, newSize);
// Close
ClosePseudoConsole(hPC);7. Console Colors (Legacy API)
// Legacy color attributes (before VT support)
#define FOREGROUND_BLUE 0x0001
#define FOREGROUND_GREEN 0x0002
#define FOREGROUND_RED 0x0004
#define FOREGROUND_INTENSITY 0x0008
#define BACKGROUND_BLUE 0x0010
#define BACKGROUND_GREEN 0x0020
#define BACKGROUND_RED 0x0040
#define BACKGROUND_INTENSITY 0x0080
// Set text color
SetConsoleTextAttribute(hStdOut,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY);8. Reading Console Input
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD ir;
DWORD read;
// Read single event
ReadConsoleInput(hIn, &ir, 1, &read);
switch (ir.EventType) {
case KEY_EVENT:
if (ir.Event.KeyEvent.bKeyDown) {
WCHAR ch = ir.Event.KeyEvent.uChar.UnicodeChar;
WORD vk = ir.Event.KeyEvent.wVirtualKeyCode;
// Process key
}
break;
case MOUSE_EVENT:
COORD pos = ir.Event.MouseEvent.dwMousePosition;
DWORD buttons = ir.Event.MouseEvent.dwButtonState;
// Process mouse
break;
case WINDOW_BUFFER_SIZE_EVENT:
COORD size = ir.Event.WindowBufferSizeEvent.dwSize;
// Handle resize
break;
}9. Windows Subsystem for Linux (WSL)
# List distributions
wsl --list --verbose
# Run Linux command
wsl ls -la
# Enter distribution
wsl
# Set default distribution
wsl --set-default Ubuntu
# Environment variables pass through
# Windows: PATH accessible as $PATH in WSL
# WSL: WSLENV controls variable sharing10. PowerShell Console Features
# Console size
$Host.UI.RawUI.WindowSize
$Host.UI.RawUI.BufferSize
# Cursor position
$Host.UI.RawUI.CursorPosition
# Colors
$Host.UI.RawUI.ForegroundColor = "Red"
$Host.UI.RawUI.BackgroundColor = "Black"
# Clear screen
Clear-Host
# Read key
$key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
# Set window title
$Host.UI.RawUI.WindowTitle = "My Console"11. cmd.exe Specifics
:: Set console code page to UTF-8
chcp 65001
:: Enable delayed expansion
setlocal enabledelayedexpansion
:: Colors with escape sequences (Win10+)
echo [31mRed text[0m
:: Or use prompt for colors
prompt $e[32m$p$g$e[0m
:: Clear screen
cls
:: Console dimensions
mode con cols=120 lines=5012. Detecting Windows Terminal Features
import os
def is_windows_terminal():
"""Check if running in Windows Terminal."""
return bool(os.environ.get('WT_SESSION'))
def is_conemu():
"""Check if running in ConEmu."""
return bool(os.environ.get('ConEmuANSI'))
def supports_vt_sequences():
"""Check VT sequence support on Windows."""
import sys
if sys.platform != 'win32':
return True
# Windows 10+ with VT support
import ctypes
kernel32 = ctypes.windll.kernel32
STD_OUTPUT_HANDLE = -11
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
handle = kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
mode = ctypes.c_ulong()
if kernel32.GetConsoleMode(handle, ctypes.byref(mode)):
return bool(mode.value & ENABLE_VIRTUAL_TERMINAL_PROCESSING)
return FalseCross-Platform Considerations
1. Line Endings
| Platform | Line Ending | Escape | Hex |
|---|---|---|---|
| Unix/Linux/macOS | LF | \n | 0x0A |
| Windows | CR+LF | \r\n | 0x0D 0x0A |
| Classic Mac (pre-OS X) | CR | \r | 0x0D |
Converting Line Endings
# Unix to Windows
sed 's/$/\r/' file > file.crlf
unix2dos file
# Windows to Unix
sed 's/\r$//' file > file.lf
dos2unix file
# Using tr
tr -d '\r' < file.crlf > file.lfPython
# Read with universal newlines (default)
with open('file.txt', 'r', newline=None) as f:
content = f.read()
# Write with specific line ending
with open('file.txt', 'w', newline='\n') as f: # Unix
f.write(content)
with open('file.txt', 'w', newline='\r\n') as f: # Windows
f.write(content)2. Path Separators
| Platform | Separator | Path Variable Separator |
|---|---|---|
| Unix/Linux/macOS | / | : |
| Windows | \ (also /) | ; |
Cross-Platform Path Handling
import os
from pathlib import Path
# Platform-independent path joining
path = os.path.join('dir', 'subdir', 'file.txt')
# Using pathlib (recommended)
path = Path('dir') / 'subdir' / 'file.txt'
# Normalize path separators
path = os.path.normpath(path)
# Get appropriate separator
sep = os.sep # Path separator
pathsep = os.pathsep # PATH variable separator// Node.js
const path = require('path');
// Platform-independent join
const filepath = path.join('dir', 'subdir', 'file.txt');
// Get separator
const sep = path.sep;
const delimiter = path.delimiter; // PATH separator3. Terminal Type Detection
import os
import sys
import platform
def get_terminal_info():
info = {}
# Operating system
info['os'] = platform.system() # 'Linux', 'Windows', 'Darwin'
# Terminal type
info['term'] = os.environ.get('TERM', 'unknown')
# Color support
info['colorterm'] = os.environ.get('COLORTERM', '')
# Is TTY?
info['stdin_tty'] = sys.stdin.isatty()
info['stdout_tty'] = sys.stdout.isatty()
# Terminal program
info['term_program'] = os.environ.get('TERM_PROGRAM', '')
# Windows specific
if platform.system() == 'Windows':
info['wt_session'] = os.environ.get('WT_SESSION', '') # Windows Terminal
info['conemu'] = os.environ.get('ConEmuANSI', '')
return info4. Cross-Platform Color Support
import sys
import os
def supports_color():
"""Check if the terminal supports color."""
# Forced color
if os.environ.get('FORCE_COLOR'):
return True
# No color requested
if os.environ.get('NO_COLOR'):
return False
# Not a TTY
if not hasattr(sys.stdout, 'isatty') or not sys.stdout.isatty():
return False
# Windows
if sys.platform == 'win32':
# Windows 10+ supports ANSI
import platform
version = platform.version().split('.')
if int(version[0]) >= 10:
return True
# Check for Windows Terminal or ConEmu
return bool(os.environ.get('WT_SESSION') or
os.environ.get('ConEmuANSI'))
# Unix-like - check TERM
term = os.environ.get('TERM', '')
if term == 'dumb':
return False
return True5. Portable Terminal Size
import shutil
import os
import sys
def get_terminal_size():
"""Get terminal size cross-platform."""
# Try shutil first (Python 3.3+)
try:
return shutil.get_terminal_size()
except:
pass
# Try environment variables
try:
return (int(os.environ['COLUMNS']), int(os.environ['LINES']))
except:
pass
# Try ioctl on Unix
if sys.platform != 'win32':
try:
import fcntl
import termios
import struct
result = fcntl.ioctl(0, termios.TIOCGWINSZ,
b'\x00\x00\x00\x00\x00\x00\x00\x00')
rows, cols = struct.unpack('hh', result[:4])
return (cols, rows)
except:
pass
# Default fallback
return (80, 24)6. Cross-Platform Key Input
import sys
def getch():
"""Read a single character without waiting for Enter."""
if sys.platform == 'win32':
import msvcrt
return msvcrt.getch().decode('utf-8')
else:
import tty
import termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch7. Environment Variable Differences
| Purpose | Unix | Windows |
|---|---|---|
| Home directory | $HOME | %USERPROFILE% |
| Temp directory | $TMPDIR or /tmp | %TEMP% |
| User name | $USER | %USERNAME% |
| Path separator | : | ; |
| Null device | /dev/null | NUL |
Cross-Platform Environment Access
import os
from pathlib import Path
# Home directory
home = Path.home() # Works on all platforms
# Temp directory
import tempfile
temp = tempfile.gettempdir()
# User name
user = os.environ.get('USER') or os.environ.get('USERNAME')
# Or
import getpass
user = getpass.getuser()8. Signal Differences
| Signal | Unix | Windows |
|---|---|---|
| SIGINT | Yes | Yes (Ctrl+C) |
| SIGTERM | Yes | No |
| SIGKILL | Yes | No |
| SIGWINCH | Yes | No |
| SIGHUP | Yes | No |
Cross-Platform Signal Handling
import signal
import sys
def setup_signal_handlers():
# Ctrl+C - works on all platforms
signal.signal(signal.SIGINT, handle_interrupt)
# Unix-specific signals
if sys.platform != 'win32':
signal.signal(signal.SIGTERM, handle_terminate)
signal.signal(signal.SIGHUP, handle_hangup)9. Executable Extensions
| Platform | Executables |
|---|---|
| Unix/Linux/macOS | No extension required |
| Windows | .exe, .bat, .cmd, .com |
Finding Executables
import shutil
# Find executable in PATH
path = shutil.which('python')
# Windows: searches for .exe, .bat, etc.
# Unix: searches for executable files10. Process Management Differences
| Feature | Unix | Windows |
|---|---|---|
| Fork | fork() | Not available |
| Spawn | spawn() | CreateProcess() |
| Signals | Full support | Limited |
| Process groups | Yes | Job objects |
| PTY | /dev/pts/* | ConPTY |
Cross-Platform Process Creation
import subprocess
import sys
# Works on all platforms
result = subprocess.run(['python', 'script.py'],
capture_output=True,
text=True)
# Shell commands
if sys.platform == 'win32':
subprocess.run('dir', shell=True)
else:
subprocess.run('ls -la', shell=True)11. File System Differences
| Feature | Unix | Windows |
|---|---|---|
| Case sensitivity | Yes | No (usually) |
| Hidden files | .filename | Attribute |
| Symlinks | Full support | Limited |
| Max path | 4096 chars | 260 chars (default) |
12. Shell Differences
| Feature | Bash | PowerShell | cmd.exe |
|---|---|---|---|
| Variables | $VAR | $env:VAR | %VAR% |
| Assignment | VAR=val | $var = val | set VAR=val |
| Pipes | Text streams | Object streams | Text streams |
| Exit code | $? | $LASTEXITCODE | %ERRORLEVEL% |
Advanced Topics
1. Terminal Multiplexers
tmux
# Start new session
tmux
tmux new -s session_name
# Attach to session
tmux attach -t session_name
tmux a
# Detach
Ctrl+b d
# Key bindings (after prefix Ctrl+b)
c # New window
n # Next window
p # Previous window
% # Split horizontally
" # Split vertically
o # Switch pane
x # Kill pane
z # Zoom pane (toggle)
d # Detach
[ # Enter copy mode
] # Paste
: # Command prompt
# List sessions
tmux ls
# Kill session
tmux kill-session -t session_nameGNU Screen
# Start session
screen
screen -S session_name
# Detach
Ctrl+a d
# Reattach
screen -r
screen -r session_name
# Key bindings (after prefix Ctrl+a)
c # New window
n # Next window
p # Previous window
| # Split vertically
S # Split horizontally
tab # Switch region
X # Close region
k # Kill window
d # Detach
# List sessions
screen -ls2. Terminal Recording
# script command
script output.txt # Start recording
# ... commands ...
exit # Stop recording
# With timing for playback
script -t 2>timing.txt output.txt
scriptreplay timing.txt output.txt
# asciinema
asciinema rec demo.cast
asciinema play demo.cast
asciinema upload demo.cast3. Serial Console Configuration
# Connect to serial console
screen /dev/ttyUSB0 115200
minicom -D /dev/ttyUSB0 -b 115200
picocom -b 115200 /dev/ttyUSB0
# Configure serial port
stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parenb
# Common baud rates
# 9600, 19200, 38400, 57600, 1152004. SSH and PTY Allocation
# Force PTY allocation
ssh -t user@host command
# Disable PTY allocation
ssh -T user@host command
# Multiple -t for forced allocation (through jump hosts)
ssh -tt user@host command
# Request specific terminal type
ssh -t -e none user@host 'export TERM=xterm-256color; bash'5. Unicode and Character Encoding
# Check current locale
locale
# Set UTF-8 locale
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
# Check terminal encoding capability
echo $TERM
locale charmap
# Test Unicode support
echo "Unicode test: Hello World 中文 Emoji test"
printf '\u2603' # Snowman
# Check file encoding
file -i filename.txt
# Convert encoding
iconv -f ISO-8859-1 -t UTF-8 input.txt > output.txt6. Raw Mode Programming Pattern
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
struct termios orig_termios;
void disable_raw_mode() {
tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
}
void enable_raw_mode() {
tcgetattr(STDIN_FILENO, &orig_termios);
atexit(disable_raw_mode);
struct termios raw = orig_termios;
// Input flags
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
// Output flags
raw.c_oflag &= ~(OPOST);
// Control flags
raw.c_cflag |= (CS8);
// Local flags
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
// Control characters
raw.c_cc[VMIN] = 0;
raw.c_cc[VTIME] = 1;
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}7. Querying Terminal Capabilities
# Query terminal for cursor position
printf '\e[6n'
# Response: \e[{row};{col}R
# Query terminal type (device attributes)
printf '\e[c'
# Response: \e[?{params}c
# Query background color (some terminals)
printf '\e]11;?\e\\'
# Query terminal size in pixels
printf '\e[14t'
# Query terminal size in cells
printf '\e[18t'8. Mouse Support
Enable Mouse Tracking
# Enable mouse tracking
printf '\e[?1000h' # Basic mouse tracking
printf '\e[?1002h' # Button event tracking
printf '\e[?1003h' # All motion tracking
# Disable mouse tracking
printf '\e[?1000l'
# SGR extended mode (better coordinates)
printf '\e[?1006h'Mouse Event Format
Basic mode: \e[Mbxy
M = button state (32 + button)
b = 32 + button (0=left, 1=middle, 2=right)
x = column + 32
y = row + 32
SGR mode: \e[<button;x;yM (press) or \e[<button;x;ym (release)9. Bracketed Paste Mode
# Enable bracketed paste
printf '\e[?2004h'
# Disable
printf '\e[?2004l'
# Pasted text is wrapped:
# \e[200~ <pasted content> \e[201~10. Focus Events
# Enable focus reporting
printf '\e[?1004h'
# Disable
printf '\e[?1004l'
# Focus in: \e[I
# Focus out: \e[O11. OSC Commands
# Set window title
printf '\e]0;Title\a'
printf '\e]2;Title\a'
# Set clipboard (OSC 52)
printf '\e]52;c;%s\a' "$(echo -n 'text' | base64)"
# Hyperlinks (some terminals)
printf '\e]8;;https://example.com\e\\Link Text\e]8;;\e\\'
# Working directory (some terminals)
printf '\e]7;file://%s%s\a' "$(hostname)" "$(pwd)"
# Notification (iTerm2)
printf '\e]9;Notification text\a'12. Terminal Graphics
Sixel Graphics
# Check sixel support
printf '\e[c' # Look for ;4; in response
# Display sixel image (requires sixel-enabled terminal)
img2sixel image.pngKitty Graphics Protocol
# Used by Kitty terminal for inline images
# Supports PNG, JPEG, GIFiTerm2 Image Protocol
# Display image in iTerm2
printf '\e]1337;File=inline=1:'
base64 < image.png
printf '\a'13. Building a Simple Terminal Editor
Key components: 1. Raw mode for character-by-character input 2. Screen clearing and cursor positioning 3. Reading keyboard input 4. Handling special keys (arrows, home, end) 5. Text buffer management 6. Status line display
// Basic structure
while (1) {
// Refresh screen
clear_screen();
draw_rows();
draw_status_bar();
position_cursor();
// Read input
int c = read_key();
// Process input
process_keypress(c);
}14. Quick Reference Card
Essential Commands
| Action | Unix/Linux | Windows (cmd) | PowerShell |
|---|---|---|---|
| Clear screen | clear | cls | Clear-Host |
| List directory | ls -la | dir | Get-ChildItem |
| Change directory | cd path | cd path | Set-Location |
| Show current dir | pwd | cd | Get-Location |
| Environment vars | env | set | Get-ChildItem Env: |
| Exit terminal | exit | exit | exit |
File Descriptors
| FD | Stream | Redirect |
|---|---|---|
| 0 | stdin | < file |
| 1 | stdout | > file |
| 2 | stderr | 2> file |
| &1 | stdout ref | 2>&1 |
Common Exit Codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General error |
| 2 | Misuse of command |
| 126 | Not executable |
| 127 | Not found |
| 128+N | Killed by signal N |
| 130 | Ctrl+C (SIGINT) |
Control Characters
| Key | Action |
|---|---|
| Ctrl+C | Interrupt (SIGINT) |
| Ctrl+D | EOF |
| Ctrl+Z | Suspend (SIGTSTP) |
| Ctrl+\ | Quit (SIGQUIT) |
| Ctrl+S | Pause output |
| Ctrl+Q | Resume output |
| Ctrl+L | Clear screen |