# 機能設計書 64-POSIXpty

## 概要

本ドキュメントは、GhosttyターミナルエミュレータにおけるPOSIX擬似端末（PTY）管理機能の設計を記述する。

### 本機能の処理概要

POSIX pty機能は、Unix/Linux/macOSシステム上でシェルやコマンドを実行するための擬似端末（Pseudo Terminal）を作成・管理する機能である。ptyはマスター/スレーブペアで構成され、端末エミュレータとシェルプロセス間の双方向通信を実現する。

**業務上の目的・背景**：ターミナルエミュレータは、シェルやコマンドラインプログラムと通信するために擬似端末を必要とする。PTYは実際のハードウェア端末をエミュレートし、プロセスがターミナルに接続されているかのように振る舞えるようにする。これにより、ジョブ制御、シグナル送信、ターミナルサイズ変更など、本物の端末と同等の機能を提供できる。

**機能の利用シーン**：
- Ghosttyウィンドウ/タブ/スプリット作成時のシェル起動
- リモートSSH接続でのPTY転送
- コマンドの標準入出力のターミナルへの接続

**主要な処理内容**：
1. openpty()によるマスター/スレーブペアの作成
2. ウィンドウサイズ（行数、列数、ピクセルサイズ）の設定
3. UTF-8モードの有効化（IUTF8フラグ）
4. CLOEXEC設定によるファイルディスクリプタの継承制御
5. 子プロセス用のセッションリーダー設定
6. 制御端末の設定（TIOCSCTTY）

**関連システム・外部連携**：
- POSIXシステムコール: openpty(), ioctl(), tcgetattr(), tcsetattr()
- 子プロセス: シェル（bash, zsh, fishなど）

**権限による制御**：特になし（通常のユーザー権限で動作）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能はバックグラウンドで動作し、特定の画面UIは持たない |

## 機能種別

システムリソース管理 / プロセス間通信

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| ws_row | u16 | No | 端末の行数（デフォルト100） | 正の整数 |
| ws_col | u16 | No | 端末の列数（デフォルト80） | 正の整数 |
| ws_xpixel | u16 | No | 端末のピクセル幅（デフォルト800） | 正の整数 |
| ws_ypixel | u16 | No | 端末のピクセル高さ（デフォルト600） | 正の整数 |

### 入力データソース

- レンダラー: ウィンドウサイズ変更時のサイズ情報
- 設定ファイル: 初期ウィンドウサイズ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| master | fd_t | マスター側ファイルディスクリプタ |
| slave | fd_t | スレーブ側ファイルディスクリプタ |
| Mode | struct | canonical, echoフラグを含む端末モード |

### 出力先

- マスターfd: ターミナルエミュレータ側で使用
- スレーブfd: 子プロセス（シェル）側で使用

## 処理フロー

### 処理シーケンス

```
1. PTYオープン
   └─ openpty()でマスター/スレーブペア作成
   └─ エラー時: OpenptyFailed

2. CLOEXECフラグ設定
   └─ マスターfdにCLOEXECを設定
   └─ スレーブfdは子プロセスで継承される

3. UTF-8モード設定
   └─ tcgetattr()で現在の属性取得
   └─ IUTF8フラグを設定
   └─ tcsetattr()で属性適用

4. 子プロセス準備（fork後）
   └─ シグナルハンドラのリセット
   └─ setsid()でセッションリーダーに
   └─ ioctl(TIOCSCTTY)で制御端末設定
   └─ マスター/スレーブfdクローズ

5. サイズ変更
   └─ ioctl(TIOCSWINSZ)でウィンドウサイズ設定

6. クリーンアップ
   └─ deinit()でマスターfdクローズ
```

### フローチャート

```mermaid
flowchart TD
    A[PosixPty.open] --> B[openpty呼び出し]
    B --> C{成功?}
    C -->|No| D[OpenptyFailed]
    C -->|Yes| E[CLOEXECフラグ設定]
    E --> F[tcgetattr]
    F --> G[IUTF8フラグ設定]
    G --> H[tcsetattr]
    H --> I{成功?}
    I -->|No| D
    I -->|Yes| J[PTY準備完了]

    K[fork] --> L[子プロセス]
    L --> M[childPreExec呼び出し]
    M --> N[シグナルリセット]
    N --> O[setsid]
    O --> P{成功?}
    P -->|No| Q[ProcessGroupFailed]
    P -->|Yes| R[TIOCSCTTY]
    R --> S{成功?}
    S -->|No| T[SetControllingTerminalFailed]
    S -->|Yes| U[fdクローズ]
    U --> V[exec]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-64-01 | CLOEXEC設定 | マスターfdにはCLOEXECを設定し、子プロセスに継承されないようにする | 常時 |
| BR-64-02 | UTF-8有効化 | IUTFフラグを設定してUTF-8入力を正しく処理 | 常時 |
| BR-64-03 | セッションリーダー | 子プロセスはsetsid()で新しいセッションを開始する | fork後 |
| BR-64-04 | 制御端末 | スレーブfdを制御端末として設定する | fork後 |

### 計算ロジック

該当なし

## データベース操作仕様

該当なし（本機能はデータベースを使用しない）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| OpenptyFailed | システムエラー | openpty()失敗、tcsetattr()失敗 | エラーを呼び出し元に返す |
| ProcessGroupFailed | システムエラー | setsid()失敗 | 子プロセス終了 |
| SetControllingTerminalFailed | システムエラー | TIOCSCTTY ioctl失敗 | 子プロセス終了 |
| IoctlFailed | システムエラー | サイズ設定/取得のioctl失敗 | エラーを呼び出し元に返す |
| GetModeFailed | システムエラー | tcgetattr()失敗 | エラーを呼び出し元に返す |

### リトライ仕様

該当なし（システムコールの失敗は即座にエラー返却）

## トランザクション仕様

該当なし

## パフォーマンス要件

- PTY作成は高速に完了すること（通常はミリ秒以下）
- サイズ変更は即座に反映されること

## セキュリティ考慮事項

- CLOEXECにより、exec時にマスターfdが不要なプロセスに継承されない
- 制御端末の設定により、シグナル送信が適切に制御される

## 備考

- macOSとLinux/FreeBSDでヘッダファイルやioctl定数が異なるため、プラットフォーム固有の処理がある
- TIOCSCTTYとTIOCSWINSZの定数値はmacOSでは直接指定されている

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pty.zig | `src/pty.zig` | winsize構造体（11-16行目） |
| 1-2 | pty.zig | `src/pty.zig` | Mode構造体（30-36行目） |
| 1-3 | pty.zig | `src/pty.zig` | Pty型エイリアス（18-22行目） |

**読解のコツ**: `winsize`はPOSIXのwinsize構造体と互換のextern struct。Zigのextern structはCのABIに準拠するため、システムコールに直接渡せる。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pty.zig | `src/pty.zig` | PosixPty構造体定義（86-252行目） |
| 2-2 | pty.zig | `src/pty.zig` | open関数（122-172行目） |

**主要処理フロー**:
1. **122-124行目**: winsize構造体のコピー作成
2. **128-135行目**: openpty()システムコール
3. **143-157行目**: CLOEXECフラグ設定
4. **161-166行目**: UTF-8モード設定

#### Step 3: 子プロセス準備処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pty.zig | `src/pty.zig` | childPreExec関数（215-251行目） |

**主要処理フロー**:
- **217-233行目**: シグナルハンドラのリセット（ABRT, ALRM, BUS, CHLD, FPE, HUP, ILL, INT, PIPE, SEGV, TRAP, TERM, QUIT）
- **237行目**: setsid()でセッションリーダー設定
- **240-246行目**: TIOCSCTTY ioctlで制御端末設定
- **249-250行目**: マスター/スレーブfdクローズ

#### Step 4: サイズ設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | pty.zig | `src/pty.zig` | setSize/getSize関数（192-208行目） |

**主要処理フロー**:
- **206-208行目**: TIOCSWINSZ ioctlでサイズ設定
- **195-200行目**: TIOCGWINSZ ioctlでサイズ取得

### プログラム呼び出し階層図

```
Ghosttyプロセス
    │
    └─ PosixPty.open(winsize)
           │
           ├─ openpty() [システムコール]
           │      └─ master_fd, slave_fd取得
           │
           ├─ fcntl(master_fd, F_SETFD, CLOEXEC)
           │
           ├─ tcgetattr(master_fd)
           │      └─ 現在の端末属性取得
           │
           └─ tcsetattr(master_fd, IUTF8)
                  └─ UTF-8モード有効化

fork()
    │
    └─ 子プロセス
           │
           └─ PosixPty.childPreExec()
                  │
                  ├─ sigaction() [各シグナルリセット]
                  │
                  ├─ setsid() [セッションリーダー]
                  │
                  ├─ ioctl(slave_fd, TIOCSCTTY)
                  │
                  ├─ close(slave_fd)
                  │
                  └─ close(master_fd)
                         │
                         └─ exec(shell)
```

### データフロー図

```
[入力]                    [処理]                         [出力]

winsize構造体 ────────▶ openpty() ───────▶ master_fd, slave_fd
(rows, cols, pixels)                            │
                                                 ▼
                        fcntl(CLOEXEC) ───▶ マスターfd保護
                                                 │
                                                 ▼
                        tcsetattr(IUTF8) ───▶ UTF-8有効化
                                                 │
                                                 ▼
                        [子プロセスで]
                                                 │
                        setsid() ──────────▶ 新セッション
                                                 │
                                                 ▼
                        TIOCSCTTY ─────────▶ 制御端末設定
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pty.zig | `src/pty.zig` | ソース | POSIX PTY実装 |
| Termio.zig | `src/termio/Termio.zig` | ソース | PTYを使用するターミナルIO |
| Command.zig | `src/Command.zig` | ソース | 子プロセス起動とPTY接続 |
